How to use UIApplicationDelegateAdaptor

With SwiftUI 2.0, UIApplicationDelegate is a thing of the past… well, maybe not. While the new App protocol and friends provide great, declarative abstractions over UIKit/AppKit app lifecycle APIs, their shortcomings may become evident when faced with complex scenarios - such as handling remote notifications, or handling shortcuts.

Fortunately, SwiftUI 2.0 provides us with a bridge between our two worlds:

/// A property wrapper that is used in `App` to provide a delegate from UIKit.
@available(iOS 14.0, tvOS 14.0, *)
@available(OSX, unavailable)
@available(watchOS, unavailable)
@propertyWrapper public struct UIApplicationDelegateAdaptor<DelegateType> : DynamicProperty where DelegateType : NSObject, DelegateType : UIApplicationDelegate {

    /// The underlying delegate.
    public var wrappedValue: DelegateType { get }

    /// Creates an `UIApplicationDelegateAdaptor` using a UIKit Application
    /// Delegate.
    ///
    /// The framework will initialize the provided delegate and manage its
    /// lifetime, calling out to it when appropriate after performing its
    /// own work.
    ///
    /// - Parameter delegate: the type of `UIApplicationDelegate` to use.
    public init(_ delegateType: DelegateType.Type = DelegateType.self)
}

Now, how do we use it?

Take the stock boilerplate for a cross-platform SwiftUI app:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

If we wanted this app to use a typical UIApplicationDelegate while still retaining a declarative, SwiftUI entry point - we could rewrite it like so:

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("Yay")

        return true
    }
}

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Run this code - and your app will print Yay.

That’s it!

Note that certain delegate functions, such as applicationDidFinishLaunching, do not seem to work with this approach.

 
14
Kudos
 
14
Kudos

Now read this

Fixing NSManagedObject’s ObservableObject conformance

In working with SwiftUI you may have noticed that NSManagedObject is not a particularly correct implementation of ObservableObject. Your NSManagedObject does not publish changes when any of its @NSManaged properties are mutated. There’s... Continue →