How to add an AppDelegate and a SceneDelegate to a SwiftUI app

By:

ITS

Category:

iPhone App Development

Besides SwiftUI, in 2019, Apple introduced the concept of multiple windows, where each window, more appropriately called scene, represents a UI instance of our app.

Fast forward one year later, and SwiftUI has a brand new life-cycle, dropping both UIKit’s app and scene delegates entirely. Here’s what’s left:

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

While the SwiftUI team keeps moving forward at a neck-breaking speed, not all third party libraries and, admittedly, not even all Apple’s API, are ready for the big shift:
to this day, many APIs still require either an AppDelegate or an UIScene to operate.

Does it mean that we can’t use the new SwiftUI life-cycle? No! The SwiftUI team has thought about these scenarios and provided us with the right tools. Let’s dig in.

Add an app delegate to a SwiftUI app

Along with the new SwiftUI life-cycle, the @UIApplicationDelegateAdaptor property wrapper has been introduced, letting us associate an app delegate to a SwiftUI app.

First, let’s define our UIApplicationDelegate:

class FSAppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
// …
return true
}
}

Then we can add it to our App:

@main
struct FSApp: App {
@UIApplicationDelegateAdaptor var delegate: FSAppDelegate

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

SwiftUI will both initialize and manage our delegate lifetime. No further work is necessary.

App delegate access via the environment

Environment is one of the most powerful SwiftUI features, if we conform our app delegate to ObservableObject, it will be accessible anywhere in our app:

class FSAppDelegate: NSObject, UIApplicationDelegate, ObservableObject { // 👈🏻
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
// …
return true
}

// …
}

With just this change, we can access our app delegate like any other environment object:

struct ContentView: View {
@EnvironmentObject var appDelegate: FSAppDelegate

var body: some View {
Button(“Tap me”) {
// appDelegate. …
}
}
}

Besides receiving the app life-cycle events, we can add to our app delegate any @Published properties, and views depending on it will produce a new body whenever changes are published, for example:

class FSAppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
@Published var date: Date = .now // 👈🏻

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
// 👇🏻 Publishes every second
Timer
.publish(every: 1, on: .main, in: .default)
.autoconnect()
.assign(to: &$date)
return true
}
}

struct ContentView: View {
@EnvironmentObject var appDelegate: FSAppDelegate // 👈🏻

var body: some View {
Text(appDelegate.date.formatted(date: .omitted, time: .standard))
}
}

We are trusted by over 650+ clients.
Join them by using our services and grow your business.

Get Started

SiteLogo
“At Inspire Techno Solution , our mission is to continuously innovate the best ways to train the next generation of developers and to transform the way tech education is delivered.”

Find a Career with us

Related Blogs

How to add an AppDelegate and a SceneDelegate to a SwiftUI app | Inspire Techno Solution

How to add an AppDelegate and a SceneDelegate to a SwiftUI app

Stay ahead of the curve by exploring the emerging technologies that might find their way
A Beginner’s Guide to Building Your First App | Inspire Techno Solution

A Beginner’s Guide to Building Your First App

"Embark on your iOS development journey with this comprehensive guide, covering the basics of Xcode,
Unlocking iOS 16 | Inspire Techno Solution

Unlocking iOS 16

"Get an exclusive look at the newest features and improvements introduced in iOS 16, and
1 2