In SwiftUI 5.1, I want to use AppDelegate to create an userData object. userData will also contain BLE advertisement data, which will be updated from AppDelegate, too. These data should be available to the UI to display those values.
In AppDelegate I use
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
private var centralManager : CBCentralManager!
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
In SceneDelegate I want to pass to the view using
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
@EnvironmentObject var userData: UserData
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView:
BeaconList().environmentObject(userData)
)
self.window = window
window.makeKeyAndVisible()
}
}
Compiling works fine, but when running the code I get
Thread 1: Fatal error: Reading EnvironmentObject outside View.body
If I remove the
.environmentObject(userData)
I get
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Essentially, I'm trying to make create and update the userData object from AppDelegate, and to display from SceneDelegate and view below.
How can I implement this?
SwiftUI gives us both @Environment and @EnvironmentObject property wrappers, but they are subtly different: whereas @EnvironmentObject allows us to inject arbitrary values into the environment, @Environment is specifically there to work with SwiftUI's own pre-defined keys.
Using multiple environment objectsYou can define as many environment objects as you like. The principle works precisely the same, as long as you provide an environment object through the view modifier for each requested environment object type.
New in iOS 14SwiftUI is responsible for creating that delegate and looking after its lifetime, so you can go ahead and add any other app delegate functionality to that class to have it called.
Maybe you can use the UIApplication.shared.delegate
to get the AppDelegate an access the user data:
class AppDelegate: UIResponder, UIApplicationDelegate {
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let userData = (UIApplication.shared.delegate as! AppDelegate).userData
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(userData))
self.window = window
window.makeKeyAndVisible()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With