I have a SwiftUI-Firebase Project and I'm using an App Delegate to handle push notifications. The client side generates a cloud messsaging registration token that I'd like to store in firestore along with the userID and other meta data.
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
tokenData = [
"token": fcmToken ?? ""
]
// Store token in firestore for sending notifications from server in future...
print("dataDict: \(tokenData)")
}
}
So, I need to get the tokenData, user metadata, package it into a custom object, and finally store it in firestore. I'm doing this by first creating a tokenModel:
struct FCMToken: Codable, Identifiable {
@DocumentID var id: String? = UUID().uuidString
var userID: String?
var token: String
var createdAt: Date
enum CodingKeys: String, CodingKey {
case userID
case token
case createdAt
}
}
And then I'd like to pass tokenData from the delagate into my HomeView() so that I can test whether a user is logged in:
@main
struct erisApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
HomeView(fcmTokenData: delegate.tokenData)
}
}
}
If so, I can call a method to firestore inside HomeView() to store my tokenData. The issue is that I'm unable to extract this tokenData out of the delegate. I've pretty comfortable with SwiftUI but quite new to UIKit, Protocol-Delegate pattern, and so on. Can someone guide me on how to achieve the desired result?
Thank you.
CodePudding user response:
To obtain AppDelegate properties in SwiftUI, use @UIApplicationDelegateAdaptor with the ObservableObject protocol and the @Published and @EnvironmentObject wrappers as explained in the Apple Docs here.
Add the ObservableObject protocol to your AppDelegate class. Then declare tokenData as @Published. This assumes tokenData is updated by your AppDelegate extension above.
class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
@Published var tokenData: [TokenData] = []
// application functions...
}
Add the @UIApplicationDelegateAdaptor in the App declaration, as you have done already, but modify HomeView like this:
@main
struct erisApp: App {
@UIApplicationDelegateAdaptor var delegate: AppDelegate
var body: some Scene {
WindowGroup {
HomeView()
}
}
}
Set up HomeView() with an @EnvironmentObject and then use delegate.tokenData as needed:
struct HomeView: View {
@EnvironmentObject var delegate: AppDelegate
var body: some View {
Text("Token Data: \(delegate.tokenData)")
}
}