SwiftUI - Show the data fetched from Firebase in view?
Looks to me like you really just want to have one user that you're pulling the data for, but you've set up your UserProfileViewModel
with an array of users ([UserProfileModel]
). There are a number of ways that you could take care of this. Here's one (check the code for inline comments about what is going on):
class UserProfileViewModel: ObservableObject {
@Published var user : UserProfileModel? = nil // now an optional
private var db = Firestore.firestore()
func data(){
db.collection("Users").whereField("uuidFromFirebase", isEqualTo: Auth.auth().currentUser!.uid).addSnapshotListener { (snapshot, error) in
guard let documents = snapshot?.documents else {
print("No Documents")
return
}
self.user = documents.compactMap { queryDocumentSnapshot -> UserProfileModel? in
return try? queryDocumentSnapshot.data(as: UserProfileModel.self)
}.first // Take the first document (since there probably should be only one anyway)
}
}
}
struct MainView: View {
@ObservedObject private var viewModel = UserProfileViewModel()
var body: some View {
VStack {
if let user = viewModel.user { //only display data if the user isn't nil
Text(user.username)
Text(user.firstName)
Text(user.lastName)
Text(user.email)
Text(user.uidFromFirebase)
}
}
}
}
I'd say a more traditional way of handling this might be to store your user profile document Users/uid/
-- that way you can just user document(uid)
to find it rather than the whereField
query.
Why is the data from firebase Firestore not coming into my view | Swift UI
try this approach, using .onAppear{...}
:
struct LeaderBoardView: View {
@StateObject var leaderBoardModel = LeaderBoardModel() // <-- here
var body: some View {
List(leaderBoardModel.users) { item in
Text(item.name)
}.onAppear {
leaderBoardModel.getData() // <-- here
}
}
}
The view is not updated with data from Firestore in SwiftUI
The actions inside getData()
are asynchronous. That means that what happens inside that function will not necessarily have executed by the time you call filteredProductByType()
in your init
method. So, on first run, it pretty much guarantees that filteredProducts
will be empty.
To fix this, you could, for example, call filteredProductByType
after your self.products = documents.map {
closure inside getData
.
That being said, a more efficient way of dealing with the problems would likely be to turn filteredProducts
into a computed property that generates its results when called. Something like:
var filteredProducts: [Product] {
products.filter { $0.type == self.productType }
}
Then, you'd never have to call filteredProductByType
and worry about the order that it happens.
SwiftUI: How to retrieve data from Firestore in second view?
In your DetailView
, you're creating a new instance of FoodViewModel
:
@ObservedObject var foodDatas = FoodViewModel()
That new instance has not fetched any data, and thus the index of the selection is out of bounds, because its array is empty.
You could pass your original ContentView
's copy of the FoodDataModel
as a parameter.
So, the previous line I quoted would become:
@ObservedObject var foodDatas : FoodViewModel
And then your NavigationLink
would look like this:
NavigationLink(destination: DetailView(foodDatas: foodDatas, selection: self.$selection) //... etc
SwiftUI and MVVM: How to display data from Firebase/Firestore in View?
This is all about asynchronous retrieving, so you need to return results in callback, like
class FirebaseManager {
private let db = Firestore.firestore()
func getUploadedDecks(completion: @escaping ([FlashcardDeck]) -> ()) {
db.collection(K.FSCollectionName).getDocuments { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
fatalError("error downloading documents")
}
var uploadedDecks = [FlashcardDeck]()
for document in documents{
if let deck = try? document.data(as: FlashcardDeck.self) {
uploadedDecks.append(deck)
}
}
completion(uploadedDecks) // << here !!
}
// no return !!
}
and use it as
class DownloadViewModel: ObservableObject {
@Published var decks = [FlashcardDeck]()
@Published var show = false
func fetchDecks(){
FirebaseManager().getUploadedDecks() { [weak self] decks in
DispatchQueue.main.async {
// always update UI-linked properties on main queue
self?.decks = decks
}
}
}
}
Related Topics
Characters Is Unavailable' Please Use String Directly
Scenekit Shape Between 4 Points
Why Do Two Distinct Array Literals Equal Each Other in Swift
How to Incorporate Swift Package Manager to an Existing Xcode Project
Swift 5, How to Execute Code After Fetching All Childadded from Firebase
Play Segment of Avaudiopcmbuffer
Get Compiler Error in Swift Indexof()
Value of Type 'Tags' Has No Member 'Lastused'
Swift Spritekit Arc for Dummies
How to Return a Value from a Void Closure in Swift
Initializing Property via Closure
How to Masking the Last Number in Swift
Swift Firebase Check If User Exists