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.

 
5
Kudos
 
5
Kudos

Now read this

PresentationLink broken in Xcode 11 beta 3

PresentationLink (in SwiftUI) seems to be broken in Xcode 11 beta 3. It succeeds in presenting a modal view controller the first time, but stops working thereafter. As noted in this StackOverflow post, this seems to occur when embedding... Continue →