Ну ... будет немного долго, но оно того стоит ... Я воспроизвел поведение дефектов на упрощенной модели ... и вот причина проблемы
2020- 01-22 19: 53: 41.008064 + 0200 Test [5539: 983123] [TableView] Только одно предупреждение: UITableView было приказано расположить видимые ячейки и другое содержимое, не находясь в иерархии представления (представление таблицы или одно из ее суперпредставлений имеет не был добавлен в окно). Это может привести к ошибкам, заставляя представления внутри табличного представления загружаться и выполнять компоновку без точной информации (например, границ табличного представления, сбора признаков, полей макета, вставок безопасной области и т. Д. c), а также приведет к ненужным перегрузкам производительности из-за дополнительные макеты проходит. Создайте символическую точку останова в UITableViewAlertForLayoutOutsideViewHierarchy, чтобы перехватить это в отладчике и посмотреть, что вызвало это, чтобы вы могли вообще избежать этого действия, если это возможно, или отложить его, пока представление таблицы не будет добавлено в окно. Представление таблицы: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7fd095042600; baseClass = UITableView; кадр = (0 0; 375 667); clipsToBounds = YES; авторазмер = W + H; жестRecognizers =; слой =; contentOffset: {0, -116}; contentSize: {375, 400,5}; AdjustContentInset: {116, 0, 0, 0}; dataSource: <_TtGC7SwiftUIP13 $ 7fff2c6b223419ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2 ___: 0x7fd093f62b60 >>
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *, так что он не работает, так что это только 100 * * * * * исходный код, который воспроизводит проблему (после запуска просто перейдите по любой строке и подождите 20 секунд)
// view model holding some sequence of data to be shown in List
class TestedModel: ObservableObject {
@Published var originalRange = [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
// simple detail view
struct DetachedDetailView: View {
let item: Int
var body: some View {
Text("Details of item \(item)")
}
}
// Issue demo view
struct TestNavigationLinkDestruction_Issue: View {
@ObservedObject var model = TestedModel()
var body: some View {
NavigationView {
List(model.originalRange, id: \.self) { item in
NavigationLink("Item \(item)", destination:
DetachedDetailView(item: item))
}
}
.onAppear {
// >> by this simulated async update of List while in Details
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
self.model.originalRange = [10, 20, 30, 40, 50, 60, 70, 80, 90]
}
}
}
}
И вот решение ... идея заключается в раздельном обновлении содержимого Списка и времени создания решение необходимо закрыть детали
struct TestNavigationLinkDestruction_Fixed: View {
@ObservedObject var model = TestedModel()
@State private var selected: Int? = nil
@State private var localStorage: [Int] = []
var body: some View {
NavigationView {
// List locally stored items
List(localStorage, id: \.self) { item in
NavigationLink("Item \(item)", destination:
DetachedDetailView(item: item)
.onReceive(self.model.$originalRange) { items in
if !items.contains(item) {
self.selected = nil // !!! unwind at once
}
}
, tag:item, selection: self.$selected)
}
.onReceive(self.model.$originalRange) { items in
DispatchQueue.main.async {
self.localStorage = items // !!! postpone local data update
}
}
}
.onAppear {
self.localStorage = self.model.originalRange // ! initial load from model
// >>> simulate async data update
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
self.model.originalRange = [10, 20, 30, 40, 50, 60, 70, 80, 90]
}
}
}
}
Итак ... все, что вам нужно, это принять выше к вашему коду, я уверен, что это возможно.