Мы используем SwiftUI с NavigationView.
У нас есть одно представление (ParentView), которое обновляет свои данные асинхронно через свою модель представления (ParentViewModel), а затем повторно визуализирует свое тело в соответствии с новыми данными. Когда блок завершения вызывается после того, как мы вошли во второе представление (ChildView) через NavigationLink, возникают проблемы, например приложение автоматически возвращается к первому представлению без какого-либо взаимодействия с пользователем или отсутствия вызовов блока завершения во втором представлении.
struct ParentView: View {
@ObservedObject private var viewModel = ProjectListViewModel()
var body: some View {
ForEach(viewModel.items) { item in
NavigationLink(destination: ChildView(item: item)) {
Text(item.label)
}
}.onAppear(perform: viewModel.loadData))
}
}
class ParentViewModel: ObservableObject {
@Published var items: [Item] = []
func loadData() {
loadDataAsynchronously { [weak self] newItems in
// Problems occur if this completion block is called after we have entered ChildView
self?.items = newItems
}
}
}
class Item: Identifiable { ... }
Эта ошибка возникает как на симуляторе, так и на физическом устройстве.
Идентификаторы элементов должны оставаться такими же, поскольку они передаются в PFObject.objectId, который является уникальным идентификатором базы данных из пакета SDK Parse Server.
Вам следует сменить @ObservedObject на @StateObject
@LuLuGaGa StateObject ведет себя аналогично EnvironmentObject, поскольку он создается как синглтон, не так ли? К сожалению, это не устраняет ошибку и возможно только на моделях просмотра без параметров.
Это не синглтон. StateObject похож на State, а ObservedObject похож на Binding, поэтому для View, в котором он инициализирован, требуется StateObject, чтобы показать, что он является его владельцем, и его следует сохранить. Что происходит в вашем случае, когда модель представления обновляется, представление воссоздается и инициализируется новая копия модели представления, StateObject предотвратит это.
@LuLuGaGa Большое спасибо за объяснение! Я попытался заменить ObservedObject на StateObject, но он не поддерживает параметры и, следовательно, неприменим для некоторых из наших вариантов использования - и там, где это было, описанная ошибка не была исправлена. Кроме того, мы думаем, что ObservedObject приводит к повторному рендерингу представления, но не к повторному созданию экземпляра, поэтому ViewModel остается прежним. Теперь мы заменили NavigationView на библиотека, который работает для нас, но нам все еще любопытно, можно ли исправить это поведение.





Проверьте, остается ли идентификатор элемента, видимого в ChildView, прежним.