iosswiftuiwidgetkitdynamic-island

iOS dyld: Symbol not found: _NSUserActivityTypeLiveActivity


I'm adding support for LiveActivities/Widgetkit for my iOS app. I'm still supporting older versions for iOS 14+. When checking if the user returned to the app through the LiveActivity in my SceneDelegate:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    if #available(iOS 16.2, *), isLiveActivity(activity: userActivity) {
        ...
    } else {
        let _ = handleDynamicLink(url: userActivity.webpageURL)
    }
}

with

@available(iOS 16.2, *)
public func isLiveActivity(activity: NSUserActivity) -> Bool {
    return activity.activityType == NSUserActivityTypeLiveActivity
}

Now the issue is no matter how I wrap it in #available(iOS 16.2, *) or even if I don't call isLiveActivity at all, just the presence of NSUserActivityTypeLiveActivity in the code anywhere will, on older iOS versions (tested on simulator only) throw the error:

dyld: Symbol not found: _NSUserActivityTypeLiveActivity

How am I supposed to include this check if I can't even include the symbol anywhere in my code ? I would have assumed NSUserActivityTypeLiveActivity to be a compile time constant, but it seems like it's dynamically looked up and crashes, since it isn't available in older versions of WidgetKit.


Solution

  • I think it is a bug in the SDK and recommend you file a bug with Apple about it.

    As a workaround you could do:

    public func isLiveActivity(activity: NSUserActivity) -> Bool {
            if #available(iOS 16.2, *){
                // workaround; we know that the live activity type is a global
                // variable containing the name of itself as a string via
                // a debug session on iOS 16.2
                return activity.activityType == "NSUserActivityTypeLiveActivity"
            }
            return false
        }
    

    The reason why I think it is a bug because looking at the documentation, NSUserActivityTypeLiveActivity we see it marked as iOS 14.0+ but if we were to launch the simulator with debugging (DYLD_PRINT_LIBRARIES environmental variable) as per iOS Crash Dump Analysis we see it complain:

    dyld: Symbol not found: _NSUserActivityTypeLiveActivity
      Referenced from: /Users/faisalm/Library/Developer/CoreSimulator/Devices/77B3F700-46F7-402C-91D5-11453CD73D23/data/Containers/Bundle/Application/73D71FF5-2E01-46E7-AEE9-C1BF94FC8846/useractivity-expt.app/useractivity-expt
      Expected in: /System/Library/Frameworks/WidgetKit.framework/WidgetKit
    .
    .
    DYLD_ROOT_PATH=/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 14.1.simruntime/Contents/Resources/RuntimeRoot
    

    If we were to go into the above DYLD_ROOT_PATH we could check using nm that the global variable NSUserActivityTypeLiveActivity is not present because the following command yields no matches:

    nm '/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 14.1.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/WidgetKit.framework/WidgetKit'| grep _NSUserActivityTypeLiveActivity
    

    So the global variable NSUserActivityTypeLiveActivity needs to be marked properly in the WidgetKit source code as not being available until iOS 16.1.