5

How do you do the cast below, in an App with SwiftUI Lifecycle, where AppDelegate is implemented as NSApplicationDelegateAdaptor?

let appDelegate = NSApplication.shared.delegate as! AppDelegate

// or
let appDelegate = NSApp.delegate as! AppDelegate

The above throws the following error:

Could not cast value of type 'SwiftUI.AppDelegate' (0x1e28fae40) to 'MyApp.AppDelegate' (0x102d277c0).

Background is using AppDelegate in an Extension

extension NSStatusBarButton {
    public override func mouseDown(with event: NSEvent) {
        super.mouseDown(with: event)
        let appDelegate = NSApp.delegate as! AppDelegate
        // do stuff with appDelegate on MouseDown Event
    }
}
flymg
  • 549
  • 3
  • 19

1 Answers1

5

We must not cast, because NSApp's delegate is not our delegate, but internal, which redirects some callbacks to that one injected via adapter.

We can access our delegate directly via variable of adapter:

@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

or via EnvironmentObject (for that AppDelegate have confirm to ObservableObject protocol), which is injected into ContentView for us automatically and so available inside all subviews:

struct MyView: View {
  @EnvironmentObject var appDelegate: AppDelegate

  // ...
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • I have added some background code, as the above is not available in an extension, and the cast is needed – flymg May 31 '22 at 08:36
  • 1
    Read first sentence in my answer once more... you cannot cast different classes. You have either to inject somehow your instance in the place where it is needed, or use some shared instance, like in https://stackoverflow.com/a/66160164/12299030. – Asperi May 31 '22 at 08:42