簡體   English   中英

使用 ObservableObject 時視圖不會更新

[英]View doesn't get updated when using ObservableObject

我正在嘗試使用 SwiftUI 構建 Instagram 克隆應用程序。

我正在通過Firebase獲取數據,並在每次服務器中的數據發生更改時嘗試實現 UI 更新。

出於某種原因,當我第一次打開應用程序並獲取數據時,我的視圖body被調用,但 UI 不會改變。 我什至設置了一個斷點,看到body被調用並包含正確的信息,只是 UI 沒有更新。

我在我的應用程序的幾個標簽,當我切換到另一個選項卡(不包含任何東西,但Text還),突然UI確實得到更新。

請看下面的gif:

gif

這是我的代碼:

主頁視圖

struct HomeView: View {
    @ObservedObject private var fbData = firebaseData

    var body: some View {
        TabView {
            //Home Tab
            NavigationView {
                ScrollView(showsIndicators: false) {
                    ForEach(self.fbData.posts.indices, id: \.self) { postIndex in
                        PostView(post: self.$fbData.posts[postIndex])
                            .listRowInsets(EdgeInsets())
                            .padding(.vertical, 5)
                    }
                }
                .navigationBarTitle("Instagram", displayMode: .inline)
                .navigationBarItems(leading:
                    Button(action: {
                        print("Camera btn pressed")
                    }, label: {
                        Image(systemName: "camera")
                            .font(.title)
                    })
                , trailing:
                    Button(action: {
                        print("Messages btn pressed")
                    }, label: {
                        Image(systemName: "paperplane")
                            .font(.title)
                    })
                )
            } . tabItem({
                Image(systemName: "house")
                    .font(.title)
            })

            Text("Search").tabItem {
                Image(systemName: "magnifyingglass")
                    .font(.title)
            }

            Text("Upload").tabItem {
                Image(systemName: "plus.app")
                    .font(.title)
            }

            Text("Activity").tabItem {
                Image(systemName: "heart")
                    .font(.title)
            }

            Text("Profile").tabItem {
                Image(systemName: "person")
                    .font(.title)
            }
        }
        .accentColor(.black)
        .edgesIgnoringSafeArea(.top)
    }
}

火力地基數據

let firebaseData = FirebaseData()

class FirebaseData : ObservableObject {
    @Published var posts = [Post]()

    let postsCollection = Firestore.firestore().collection("Posts")

    init() {
        self.fetchPosts()
    }

    //MARK: Fetch Data
    private func fetchPosts() {
        self.postsCollection.addSnapshotListener { (documentSnapshot, err) in
            if err != nil {
                print("Error fetching posts: \(err!.localizedDescription)")
                return
            } else {
                documentSnapshot!.documentChanges.forEach { diff in
                    if diff.type == .added {
                        let post = self.createPostFromDocument(document: diff.document)
                        self.posts.append(post)
                    } else if diff.type == .modified {
                        self.posts = self.posts.map { (post) -> Post in
                            if post.id == diff.document.documentID {
                                return self.createPostFromDocument(document: diff.document)
                            } else {
                                return post
                            }
                        }
                    } else if diff.type == .removed {
                        for index in self.posts.indices {
                            if self.posts[index].id == diff.document.documentID {
                                self.posts.remove(at: index)
                            }
                        }
                    }
                }
            }
        }
    }

    private func createPostFromDocument(document: QueryDocumentSnapshot) -> Post {
        let data = document.data()

        let id = document.documentID
        let imageUrl = data["imageUrl"] as! String
        let authorUsername = data["authorUsername"] as! String
        let authorProfilePictureUrl = data["authorProfilePictureUrl"] as! String
        let postLocation = data["postLocation"] as! String
        let postDescription = data["postDescription"] as! String
        let numberOfLikes = data["numberOfLikes"] as! Int
        let numberOfComments = data["numberOfComments"] as! Int
        let datePosted = (data["datePosted"] as! Timestamp).dateValue()
        let isLiked = data["isLiked"] as! Bool

        return Post(id: id, imageUrl: imageUrl, authorUsername: authorUsername, authorProfilePictureUrl: authorProfilePictureUrl, postLocation: postLocation, postDescription: postDescription, numberOfLikes: numberOfLikes, numberOfComments: numberOfComments, datePosted: datePosted, isLiked: isLiked)
    }
}

如果您需要我發布更多代碼,請告訴我。

更新:

帖子視圖

struct PostView: View {
    @Binding var post: Post

    var body: some View {
        VStack(alignment: .leading) {
            //Info bar
            HStack {
                WebImage(url: URL(string: post.authorProfilePictureUrl))
                    .resizable()
                    .frame(width: 40, height: 40)
                    .clipShape(Circle())

                VStack(alignment: .leading, spacing: 2) {
                    Text(post.authorUsername).font(.headline)
                    Text(post.postLocation)
                }

                Spacer()

                Button(action: {
                    print("More options pressed")
                }, label: {
                    Image(systemName: "ellipsis")
                        .font(.title)
                        .foregroundColor(.black)
                }).buttonStyle(BorderlessButtonStyle())
            }
            .padding(.horizontal)

            //Main Image
            WebImage(url: URL(string: post.imageUrl))
              .resizable()
              .aspectRatio(contentMode: .fit)

            //Tools bar
            HStack(spacing: 15) {
                Button(action: {
                    self.post.isLiked.toggle()
                    print("Like btn pressed")
                }, label: {
                    Image(systemName: post.isLiked ? "heart.fill" : "heart")
                        .font(.title)
                        .foregroundColor(.black)
                }).buttonStyle(BorderlessButtonStyle())

                Button(action: {
                    print("Comments btn pressed")
                }, label: {
                    Image(systemName: "message")
                        .font(.title)
                        .foregroundColor(.black)
                }).buttonStyle(BorderlessButtonStyle())

                Button(action: {
                    print("Share btn pressed")
                }, label: {
                    Image(systemName: "paperplane")
                        .font(.title)
                        .foregroundColor(.black)
                }).buttonStyle(BorderlessButtonStyle())

                Spacer()

                Button(action: {
                    print("Bookmark btn pressed")
                }, label: {
                    Image(systemName: "bookmark")
                        .font(.title)
                        .foregroundColor(.black)
                }).buttonStyle(BorderlessButtonStyle())
            }.padding(8)

            Text("Liked by \(post.numberOfLikes) users")
                .font(.headline)
                .padding(.horizontal, 8)

            Text(post.postDescription)
                .font(.body)
                .padding(.horizontal, 8)
                .padding(.vertical, 5)

            Button(action: {
                print("Show comments btn pressed")
            }, label: {
                Text("See all \(post.numberOfComments) comments")
                    .foregroundColor(.gray)
                    .padding(.horizontal, 8)
            }).buttonStyle(BorderlessButtonStyle())

            Text(post.datePostedString)
                .font(.caption)
                .foregroundColor(.gray)
                .padding(.horizontal, 8)
                .padding(.vertical, 5)
        }
    }
}

發布

struct Post : Identifiable, Hashable {
    var id: String
    var imageUrl: String
    var authorUsername: String
    var authorProfilePictureUrl: String
    var postLocation: String
    var postDescription: String
    var numberOfLikes: Int
    var numberOfComments: Int
    var datePostedString: String

    var isLiked: Bool

    init(id: String, imageUrl: String, authorUsername: String, authorProfilePictureUrl: String, postLocation: String, postDescription : String, numberOfLikes: Int, numberOfComments: Int, datePosted: Date, isLiked: Bool) {
        self.id = id
        self.imageUrl = imageUrl
        self.authorUsername = authorUsername
        self.authorProfilePictureUrl = authorProfilePictureUrl
        self.postLocation = postLocation
        self.postDescription = postDescription
        self.numberOfLikes = numberOfLikes
        self.numberOfComments = numberOfComments

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMMM dd, yyyy"
        self.datePostedString = dateFormatter.string(from: datePosted)

        self.isLiked = isLiked
    }
}

謝謝!

問題是,當應用程序啟動時,您的數組為空,並且 ScrollView 停止更新,您可以將其替換為 VStack 並且它會起作用(僅用於測試)。

解決方案是使用條件包裝ForEach (或 ScrollView),如下所示:

if (fbData.posts.count > 0) {
    ForEach(self.fbData.posts.indices, id: \.self) { postIndex in
        PostView(post: self.$fbData.posts[postIndex])
            .listRowInsets(EdgeInsets())
            .padding(.vertical, 5)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM