Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicit instantiation for macOS apps #78

Open
mpdifran opened this issue Dec 31, 2017 · 4 comments
Open

Explicit instantiation for macOS apps #78

mpdifran opened this issue Dec 31, 2017 · 4 comments

Comments

@mpdifran
Copy link
Member

The README mentions you can do something like this in iOS apps to explicitly load your root view controller from SwinjectStoryboard:

let window = UIWindow(frame: UIScreen.mainScreen().bounds)
window.makeKeyAndVisible()
self.window = window

let storyboard = SwinjectStoryboard.create(name: "Main", bundle: nil, container: container)
window.rootViewController = storyboard.instantiateInitialViewController()

Is there an equivalent practice for macOS?

@jakubvano
Copy link
Member

jakubvano commented Feb 14, 2018

I don't typically do OSX development, so can't comment on recommended practices.
It would definitely be welcomed if someone well versed in OSX apps gave some pointers.

@mpdifran
Copy link
Member Author

mpdifran commented Feb 11, 2019

My current workaround is to let the app load via storyboard, and then call this method in applicationDidFinishLaunching(_ aNotification: Notification).

func setupWindow() {
    let storyboard = SwinjectStoryboard.create(name: "Main", bundle: nil)

    guard let window = NSApplication.shared.windows.first(where: { $0.delegate is MainWindowController }),
        let mainWindowController = storyboard.instantiateInitialController() as? MainWindowController else { return }

    window.windowController = mainWindowController
    window.makeKeyAndOrderFront(self)
}

One thing to note though (not sure if this is a separate bug or a side effect of doing the above) but I'm noticing storyboardInitComplete() is called after windowDidLoad(). This behavior is different than on iOS, where they're called in the opposite order.

@armintelker
Copy link

armintelker commented Mar 15, 2019

@mpdifran Hey i am not sure if I understand you correct but you can remove the storyboard from the Info.plist
you need to add your own NSApplication

import Foundation
import Cocoa

class CustomApplication: NSApplication {
    
    let strongDelegate = AppDelegate()
    
    override init() {
        super.init()
        self.delegate = strongDelegate
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

and you need to add/replace this class to the info plist

	<key>NSPrincipalClass</key>
	<string>your_project_name.CustomApplication</string>

if you have a problem to get the correct project name just start your app and add this line somewhere in your project and you will get in the console your project name.

print(String(describing: self))
class AppDelegate: NSObject, NSApplicationDelegate {
    private var storyboard: SwinjectStoryboard!
    private var windowController: NSWindowController!
    let container = Injections().container
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        storyboard = SwinjectStoryboard.create(name: "Main", bundle: nil, container: container)
    
        windowController = storyboard.instantiateInitialController() as! NSWindowController?
        windowController?.showWindow(self)
    }
}


@mpdifran
Copy link
Member Author

Ah that's perfect. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants