Michael Rowe
Michael Rowe

Reputation: 956

WatchKit App Get's Nil when initializing class

I am trying to update my app to utilize SwiftUI architecture. It is a stand alone WatchKit app. I used to pass a few key classes between views utilizing the delegate approach. Since I am trying to utilize environmentObject, I would like to initialize the initial classes (which depend on each other) via the delegate.
Given I am using SwiftUI method, I have recreated AppDelegate in the @main.

import SwiftUI

class AppDelegate: NSObject, WKExtensionDelegate {
    var class1: Class1?
    var class2: Class2! = Class2()
    var class3: Class3!

    func application(_ application: WKExtension) -> Bool {
        return true
    }
}


@main
struct WatchApp: App {
    
    @WKExtensionDelegateAdaptor(AppDelegate.self) var delegate
    
    init() {
        delegate.class1 = Class1()
        delegate.class2 = Class2()
        delegate.class3 = Class3()
    }

    @SceneBuilder var body: some Scene {
        WindowGroup {
            NavigationView {
                ContentView()
                    .environmentObject(delegate.class3)
                    .environmentObject(delegate.class2)
                    .environmentObject(delegate.class1)
            }
        }

        WKNotificationScene(controller: NotificationController.self, category: "myCategory")
    }
}

When Class 3 get's called I get a nil value in the access of the AppDelegate and a crash.

    
    #if os(macOS)
    let delegate = NSApplication.shared.delegate as! AppDelegate
    #elseif !os(watchOS)
    let delegate = UIApplication.shared.delegate as! AppDelegate
    #else
    let delegate = WKExtension.shared().delegate as! AppDelegate //<HERE's The Crash - Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    #endif

}

And in the info.plist

<key>WKExtensionDelegateClassName</key>
    <string>$(PRODUCT_MODULE_NAME).AppDelegate</string>

Is there an obvious thing I am overlooking?

Upvotes: 0

Views: 329

Answers (1)

Itay Brenner
Itay Brenner

Reputation: 810

WKExtension.shared() is always defined, but delegate property may be nil. Using as! is what crashes your app

You will have to provide a delegate to handle lifecycle events in your extension, see Apple Doc

To assign an AppDelegate for the extension, follow this steps:

  1. Create a class with name YOUR_CLASS_ExtensionDelegate that implements the protocol WKExtensionDelegate.
  2. Make sure the value of WKExtensionDelegateClassName in Info.plist in WatchKit Extension is $(PRODUCT_MODULE_NAME).YOUR_CLASS_ExtensionDelegate

In your case, you already did 1, but you should check for 2

Upvotes: 1

Related Questions