Ошибка при изменении представления из другого представления SwiftUI - PullRequest
0 голосов
/ 09 мая 2020

Я много искал об этой ошибке, но, похоже, решения нет ...

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!))")**
            }
        }
    }
}

Я только что выделил жирным шрифтом, что делает эта ошибка, и я не знаю, как ее избежать, потому что если я запускаю приложение, оно не треснет sh, но я ничего не могу сделать. Заранее спасибо

1 Ответ

0 голосов
/ 11 августа 2020

У вас есть пара проблем. Во-первых, когда вы используете ForEach, если предполагается, что ваш контент может изменяться (что, с FetchRequest это ...), то либо FavoriteBooks должно быть Identifiable, либо вам нужно передать в вашем id. Фактически вы делаете это дважды в коде:

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

Обратите внимание, теперь вы сообщаете ему, что такое идентификатор. Если количество bookData.booksData изменится, теперь SwiftUI может исправить эти изменения. Но действительно, зачем именно в этом случае нужен индекс? Почему не просто:

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

Если вы сделаете этот тип объекта совместимым с Identifiable, теперь у вас уже есть книга.

Теперь перейдем к другой проблеме, действию вашей кнопки. Почему вы повторно выполняете запрос CoreData здесь? У вас есть Set нужных вам объектов. Это еще одна причина просто использовать ForEach(bookData.booksData), здесь вам не нужно разрешать индекс. Но в целом вам не следует никогда повторно выполнять запрос основных данных, чтобы найти определенный c объект. на самом деле это вызывает еще одно обновление всей иерархии представлений, что, вероятно, является причиной того, что вы получаете ошибку, которую получаете. вы не должны этого делать.

...