SwinjectStoryboard icon indicating copy to clipboard operation
SwinjectStoryboard copied to clipboard

Explicit instantiation for macOS apps

Open mpdifran opened this issue 6 years ago • 4 comments

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?

mpdifran avatar Dec 31 '17 18:12 mpdifran

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.

jakubvano avatar Feb 14 '18 15:02 jakubvano

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.

mpdifran avatar Feb 11 '19 02:02 mpdifran

@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)
    }
}


armintelker avatar Mar 15 '19 23:03 armintelker

Ah that's perfect. Thank you!

mpdifran avatar Mar 15 '19 23:03 mpdifran