Hi. I'm working on a basic event planner app to learn about how to program with Swiftui and how to load asynchronous data from a database.
My app opens, makes a request to Firebase to check the login status, retrieves the user, and their relationships, and then loads whatever posts their "friends" have made. I try to append those posts into an array in a view model for a homepage that presents them in a scroll view. While I'm certain that the objects of class FBEvent append, the view does not update. I'll share the code and the result of my copious print statements below.
This is occurring in the HomeFeedView with the HomeFeedModel. I have added further blocks of code so that you can get a better sense of my layout and when the data is loaded, but you can probably treat that portion as a black box- I know that the proper data of type FBEvent (a class that implements ObservableObject protocol) is added to the array in the HomeFeedModel once the UsersInfo receives it's FBUser object from the database (see the console print.) But when these have been added, the view does not update, ie it still displays the SunLoadView (just an activity indicator). Any ideas?
// HomeFeedModel.swift
// MyProj
//
// Created by Karrsen Bryant on 9/20/21.
//
import Foundation
import SwiftUI
class HomeFeedModel: ObservableObject{
@Published var events: [FBEvent] = []
var loggedInUser: UsersInfo
func setLoggedInUserUserData(usersInfo: UsersInfo){
self.loggedInUser = usersInfo
}
func loadEvents(fBUser: FBUser){
//!!!If statement represents what type of homefeed load we are using,
//currently just doing a load among friends!!!
//Later base this on state
print("got to loading of events!")
print("relationships: \(fBUser.relationships)")
for relationship in fBUser.relationships{
if(relationship.value == "friends"){
FBFireStoreFunctions.queryFBEvents(field: "oP", value: relationship.key) { (result) in
switch result{
case .success(let eventsToAdd):
print("adding data to events array")
print("\(eventsToAdd)")
self.events.append(contentsOf: eventsToAdd)
case .failure(let err):
print("failed to get event documents for \(relationship.key)")
}
print("events now: \(self.events)")
}
}
}
}
}
init (eo: UsersInfo){
self.loggedInUser = eo
}
}
//
// HomeFeed.swift
// MyProj
//
// Created by Karrsen Bryant on 9/20/21.
//
import SwiftUI
struct HomeFeedView: View{
@EnvironmentObject var loggedInUser: UsersInfo
@ObservedObject var stateManager: HomeFeedModel
var testData: [FBEvent]
let color = Color(red: 0.8, green: 0.7, blue: 1.0)
var body: some View {
ZStack {
VStack {
HomeTopBarView()
if(stateManager.events.count == 0){
Spacer()
SunLoadView()
Spacer()
} else {
ScrollView{
ForEach(stateManager.events){ event in
EventView(event: event, loggedInUser: loggedInUser, activeStateManager: EventViewStateManager())
.frame(minWidth: 0, idealWidth: 100, maxWidth: 500, minHeight: 0, idealHeight: 100, maxHeight: 500, alignment: .center)
.padding(EdgeInsets(top: 15, leading: 10,
bottom: 10, trailing: 10))
}
}
}
}
PostViewNavButtonBottomTrailing()
}
.hiddenNavigationBarStyle()
.onReceive(loggedInUser.$user) { (pubOut) in
print("new value for logged in user! \(pubOut.name)")
print("with friends: \(pubOut.relationships)")
stateManager.loadEvents(fBUser: pubOut)
}
.onReceive(stateManager.$events) { (pubOut) in
print("New events array value! \(pubOut)")
}
}
}
struct HomeFeedView_Previews: PreviewProvider{
static var testData: [FBEvent] = TestingTruthSource.testData
static var userInfo = UsersInfo()
static var vm = HomeFeedManager(eo: userInfo)
static var previews: some View{
Group {
NavigationView{
HomeFeedView(stateManager: vm, testData: testData)
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(true)
}
}
}
}
The rest can probably be treated as a black box, but I'l just add it in case you guys want to peruse more code.
PS. I know a lot of this might not be the most efficient and is likely messy. I code with a "get it done, fix it later" style. Sorry if that makes everything difficult to parse.