Debugging NSUserActivity in SwiftUI can be painful—failures are silent and timing is unpredictable.
— Kyle Ye (@KyleSwifter) February 1, 2026
There's a hidden flag that helps: _defaultSwiftUIActivityEnvironmentLoggingEnabled
See more info on https://t.co/ucnoh2omiN #SwiftUI
SwiftUI's userActivity and onContinueUserActivity modifiers enable powerful features like Handoff, Spotlight indexing, and Siri Shortcuts. But debugging these can be challenging—activities are system-managed, updates happen at unpredictable intervals, and failures often occur silently. There's a hidden debugging flag that can help.
The Debug Flag
Set _defaultSwiftUIActivityEnvironmentLoggingEnabled to true early in your app's lifecycle:
import SwiftUI
@main
struct MyApp: App {
init() {
#if DEBUG
_defaultSwiftUIActivityEnvironmentLoggingEnabled = true
#endif
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
What It Logs
Once enabled, SwiftUI logs detailed information about the userActivity lifecycle:
Preference Changes: WhenuserActivitymodifiers are added, removed, or updated
Handler Invocations: When your update closure is called
Activity Updates: The actualNSUserActivitytitle anduserInfoafter updates
Activation Conditions: Changes tohandlesExternalEvents(preferring:allowing:)predicates
Example console output:
UserActivityPreferences changed: ...
Initializing advertised user activity:
Invoking handler for ViewIdentity(...)
updated user activity "View Document" with userInfo ["documentID": "abc123"]
Common Issues the Logging Helps Debug
Activity not appearing in Handoff: Check if the handler is being invoked and verify isEligibleForHandoff = true is set.
Spotlight search not working: Verify isEligibleForSearch = true and that title is set. The logging shows exactly what's being advertised.
Wrong scene receiving activity: The activation conditions logging shows the predicate matching logic. Verify your preferring and allowing sets are correct.
Updates not being saved: The logging shows when needsSave triggers updates. If you don't see "updated user activity" messages, your handler may not be returning or the activity type doesn't match.
Requirements
- SwiftUI Lifecycle (not UIKit AppDelegate lifecycle)
- Activity types declared in
Info.plistunderNSUserActivityTypes - Same developer team for cross-device Handoff
Using the UIKit lifecycle with scene delegates will produce a warning:
Cannot use Scene methods for URL, NSUserActivity, and other External Events without using SwiftUI Lifecycle.
Implementation Details
The logging is implemented in SwiftUI's SceneBridge, which manages the connection between your views and the underlying scene infrastructure. The OpenSwiftUI implementation reveals how activities flow through the system:
- Views declare activity preferences via the
userActivitymodifier - Preferences propagate up the view hierarchy and merge
SceneBridge
receives preference changes and managesNSUserActivityinstances- The activity's delegate (
userActivityWillSave) triggers your update handlers - Activities are attached to the root view controller (iOS) or window (macOS)
Further Reading
For comprehensive coverage of NSUserActivity features in SwiftUI, see Javier's excellent article: NSUserActivity with SwiftUI which covers Handoff, Spotlight Search, Universal Links, and Siri Shortcuts in depth.