Интерфейс изменяется с ObservableObject сразу после переключения вкладок - PullRequest
0 голосов
/ 18 марта 2020

У меня есть ObservableObject, который я использую для обновления моего пользовательского интерфейса при отправке новых данных с сервера (класс, который содержит массив пользовательских структур).

По некоторым причинам, когда данные ContentView body вызывается, но данные не изменяются. Я даже добавил оператор print, чтобы проверить, правильны ли данные, содержащиеся в массиве.

Когда я пытаюсь перейти на другую вкладку в моем TabView, а затем переключиться обратно на главную вид, пользовательский интерфейс действительно обновляется. Кто-нибудь знает, почему пользовательский интерфейс обновляется только тогда, когда я переключаю вкладки, хотя body вызывается для обновления пользовательского интерфейса при изменении данных?

HomeView

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("MyPhotoApp", 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)
    }
}

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)
                            }
                        }
                    }
                }
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 19 марта 2020

Я думаю, это ошибка SwiftUI. Я решаю эту проблему следующим образом. Вместо рендеринга вашего PostView (post: self. $ FbData.posts [postIndex]) реализуйте представление сообщений внутри ForEach.

ForEach(self.fbData.posts.indices, id: \.self) { postIndex in
   Text(self.$fbData.posts[postIndex].comment)
   Text(self.$fbData.posts[postIndex].date)
   ....
}
0 голосов
/ 18 марта 2020

Ваш пример кода не помогает найти ошибку. Наконец-то я понял, как это продемонстрировать. Во-первых, сделайте это «надлежащим образом» (скопируйте - вставьте - попробуйте сами)

import SwiftUI

struct Data: Identifiable {
    let id = UUID()
    let text: String
}
class Model: ObservableObject {
    @Published var data: [Data] = [Data(text: "alfa"), Data(text: "beta")]
 }

struct ContentView: View {
    @ObservedObject var model = Model()
    var body: some View {
        TabView {
            View1(model: model).tabItem {
                Text("View 1")
            }
            View2(model: model).tabItem {
                Text("View 2")
            }
        }
    }
}

struct View1: View {
    @ObservedObject var model: Model
    var body: some View {
        VStack {
            Text("View 1").font(.largeTitle)
            DataView(data: model.data)
            Button(action: {
                self.model.data.append(Data(text: String("ABCDEFGH".shuffled())))
            }) {
                Text("Add random data")
            }
        }
    }
}
struct View2: View {
    @ObservedObject var model: Model
    var body: some View {
        VStack {
            Text("View 2").font(.largeTitle)
            DataView(data: model.data.filter({ (item) -> Bool in
                item.text.count < 4
                }))
                // to distinguish from other DataView !! it seems to be a bug in SwiftUI
                // try to remove it to see the difference
                .id("view2")
            Button(action: {
                self.model.data.append(Data(text: String("ABC".shuffled())))
            }) {
                Text("Add random data")
            }
        }
    }
}

struct DataView: View {
    var data: [Data]
    var body: some View {
        List {
            ForEach(data) { (item) in
                Text(item.text)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Я работаю так, как нужно, вы можете изменять данные на каждой вкладке, вы видите обновленные данные и т. Д. c.

enter image description here

при удалении модификатора .id, определенного пользователем, он резко меняет поведение

enter image description here

Это похоже на серьезную ошибку в SwiftUI ...

...