首页 > 解决方案 > 从另一个视图 SwiftUI 修改视图时出错

问题描述

我搜索了很多有关此错误的信息,但似乎没有解决方案...

UITableView was told to layout its visible cells and other contents without being in the
view hierarchy (the table view or one of its superviews has not been added to a window). 
This may cause bugs by forcing views inside the table view to load and perform layout without
accurate information (e.g. table view bounds, trait collection, layout margins, safe area 
insets, etc), and will also cause unnecessary performance overhead due to extra layout passes.
Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in
the debugger and see what caused this to occur, so you can avoid this action altogether if
possible, or defer it until the table view has been added to a window

这是我的实际代码:

    struct ContentView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: FavoriteBooks.getAllFavoriteBooks()) var favoriteBooks:FetchedResults<FavoriteBooks>

    @ObservedObject var bookData = BookDataLoader()

    var body: some View {
        NavigationView {
            List {
                Section {
                    NavigationLink(destination: FavoriteView()) {
                        Text("Go to favorites")
                    }
                }
                Section {
                    ForEach(0 ..< bookData.booksData.count) { num in
                        HStack {
                            Text("\(self.bookData.booksData[num].titolo)")

                            Button(action: {
                                **let favoriteBooks = FavoriteBooks(context: self.managedObjectContext)
                                favoriteBooks.titolo = self.bookData.booksData[num].titolo**
                            }) {
                                Image(systemName: "heart")
                            }
                        }
                    }
                }
            }
        }
    }
}

struct FavoriteView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: FavoriteBooks.getAllFavoriteBooks()) var favoriteBooks:FetchedResults<FavoriteBooks>

    var body: some View {
        List {
            **ForEach (self.favoriteBooks) { book in
                Text("\(book.titolo!))")**
            }
        }
    }
}

我刚刚选择了粗体是什么导致了这个错误,我不知道如何避免它,因为如果我启动应用程序它不会崩溃但我什么也做不了。提前致谢

标签: swiftviewswiftui

解决方案


你在这里有几个问题。首先是,ForEach当您使用. 您实际上在代码中执行了两次:FetchRequestFavoriteBooksIdentifiableid

ForEach(0 ..< bookData.booksData.count) { num in
  // SwiftUI thinks this content never changes because it doesn't know how to resolve those changes. you didn't tell it
}

应该:

ForEach(0 ..< bookData.booksData.count, id: \.self) { ... }

注意现在你告诉它 id 是什么。如果计数bookData.booksData变化,现在 SwiftUI 可以解决这些变化。但实际上,为什么在这种情况下需要专门的索引呢?为什么不只是:

ForEach(bookData.booksData) { book in ... }

如果您使此对象类型符合Identifiable,那么您现在已经拥有了这本书。

现在转到另一个问题,您的按钮操作。为什么要在这里重新执行 CoreData 查询?你有Set你想要的对象。这是使用的另一个原因ForEach(bookData.booksData),您不必在这里解析索引。但一般来说,您永远不需要重新执行核心数据查询来查找特定对象。这实际上会触发整个视图层次结构的另一个更新,这可能是您收到错误的原因。你不应该这样做。


推荐阅读