I have the same problem. Simulator works as expected and the keyboard button shows, but when I test the build on a device it isn't visible.
Post
Replies
Boosts
Views
Activity
Hello Appeloper! First I just want to say I really do enjoy this approach versus MVVM. Being new to SwiftUI and seeing the MVVM approach it seemed so bloated and incredibly counter to what I saw in WWDC talks in their more simple demos (very much draw the rest of the owl).
I want to ask about what is the best approach for a Store approach when you have an Account object that retrieves information about a user (in my case firebase auth) and then uses an identifier in that auth information as a path identifier for another store (e.g. firestore).
I have a collection for say Books/<userId>/ and want to have a bookstore as you've described. Do you simply pass in the userId to the .loadStore function? Or should the BookStore contain a reference itself to the underlying auth provider?
@MainActor
class Account: ObservableObject {
@Published var isLogged: Bool = false
@Published var userDetails: UserDetails? = nil
@Published var error: Error? = nil
private var firebaseUser: User?
private var authStateChangeHandler: AuthStateChangeHandler?
private var userService: UserService = UserService.shared
private var authService: AuthenticationService = AuthenticationService.shared
private let logger = Logger(subsystem: "...", category: "Account")
init() {
authService.subscribeAuthStateChange { [weak self] (user: User?) in
guard let self = self else { return }
if let user = user {
firebaseUser = user
isLogged = true
} else {
firebaseUser = nil
isLogged = false
}
}
}
func login(email: String, password: String) async {
do {
try await authService.login(email: email, password: password)
} catch {
self.error = error
}
}
func register(email: String, password: String) async {
do {
try await authService.register(email: email, password: password)
} catch {
self.error = error
}
}
func loadUser() async {
do {
guard let firebaseUser = firebaseUser else {
throw UserError.noUserId
}
userDetails = try await userService.fetchUser(with: firebaseUser.uid)
error = nil
logger.info("User loaded \(firebaseUser)")
} catch {
self.error = error
}
}
}
class FirebaseAuthProvider: AuthenticationProvider {
private let auth = Auth.auth() // <- should this become shared and used inside the stores?
}
I'm honestly lost on the automatic inverse relationships. I've reviewed the SampleTrips project and followed what they do there and it doesn't work.
From what I can see, you don't need to do anything other than mark the inverse and then:
let item = BucketListItem(
title: "A bucket list item title",
details: "Details of my bucket list item",
hasReservation: true, isInPlan: true)
item.trip = .preview
but when I review the code of the project in the section where they add bucket list items, they do set the inverse?
private func addItem() {
withAnimation {
let newItem = BucketListItem(title: title, details: details, hasReservation: hasReservations, isInPlan: isInPlan)
modelContext.insert(newItem)
newItem.trip = trip
trip.bucketList.append(newItem)
}
}
this doesn't seem to make sense to me?