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.