mhdhejazi / Dynamic

Call hidden/private API in style! The Swift way.
https://medium.com/@mhdhejazi/calling-ios-and-macos-hidden-api-in-style-1a924f244ad1
Apache License 2.0
695 stars 36 forks source link

Mac Catalyst applicationShouldTerminateAfterLastWindowClosed #10

Open tommycarpi opened 3 years ago

tommycarpi commented 3 years ago

Hi guys, I've got another question, with Dynamic on Mac Catalyst is it possible to include applicationShouldTerminateAfterLastWindowClosed in the AppDelegate?

#if targetEnvironment(macCatalyst)
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
// ...
}
#endif

Thanks in advance

polymerchm commented 3 years ago

Not clear to me that method is exposed in ApplicationDelegate. Only in NSApplicationDelegate. Likely, you will need to create an observer for the notification, if you can figure out what the notification string is.

I leave this to Mhd.

mman commented 3 years ago

I have tried to set my custom NSApplicationDelegate using the loaded AppKit bundle trick to achieve this, but Catalyst did override/ignore my custom delegate, and it did not work. I'm also interested how to make this work.

tommycarpi commented 3 years ago

I managed to subscribe to some notifications in order to be alerted upon resignation and activation. I couldn't solve the ShouldTerminateAfterLastWindowClosed yet, but that's a start.

Here is the code for future reference:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    #if targetEnvironment(macCatalyst)
    NotificationCenter.default.addObserver(self, selector: #selector(resignActive), name: NSNotification.Name("NSApplicationDidResignActiveNotification"),object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(becomingActive), name: NSNotification.Name("NSApplicationDidBecomeActiveNotification"),object: nil)
    #endif
}

@objc func resignActive() {
    // ... your code
  }

@objc func becomingActive() {
    // ... your code
}
mman commented 1 year ago

More debugging here: If you hook into the app/scene lifecycle, you will see that NSApplication.shared.delegate is actually nil until first scene completes loading. Only after that it makes sense to actually swap the NSApplicationDelegate class.

However, Mac Catalyst app actually expects the NSApplicationDelegate to be of class UINSApplicationDelegate, whose dump can be found for example here: https://github.com/w0lfschild/macOS_headers/blob/master/macOS/PrivateFrameworks/UIKitMacHelper/61000/UINSApplicationDelegate.h and that delegate implements couple of undocumented methods and variables that you need to cope with.

No success so far on my side.