SwiftUI повторно отображает неактивное представление после асинхронного обновления свойства @Published

Мы используем 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 { ... }

Эта ошибка возникает как на симуляторе, так и на физическом устройстве.

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

Asperi 07.04.2021 13:26

Идентификаторы элементов должны оставаться такими же, поскольку они передаются в PFObject.objectId, который является уникальным идентификатором базы данных из пакета SDK Parse Server.

Philipp Fahlteich 07.04.2021 13:29

Вам следует сменить @ObservedObject на @StateObject

LuLuGaGa 07.04.2021 15:10

@LuLuGaGa StateObject ведет себя аналогично EnvironmentObject, поскольку он создается как синглтон, не так ли? К сожалению, это не устраняет ошибку и возможно только на моделях просмотра без параметров.

Philipp Fahlteich 07.04.2021 19:02

Это не синглтон. StateObject похож на State, а ObservedObject похож на Binding, поэтому для View, в котором он инициализирован, требуется StateObject, чтобы показать, что он является его владельцем, и его следует сохранить. Что происходит в вашем случае, когда модель представления обновляется, представление воссоздается и инициализируется новая копия модели представления, StateObject предотвратит это.

LuLuGaGa 07.04.2021 19:13

@LuLuGaGa Большое спасибо за объяснение! Я попытался заменить ObservedObject на StateObject, но он не поддерживает параметры и, следовательно, неприменим для некоторых из наших вариантов использования - и там, где это было, описанная ошибка не была исправлена. Кроме того, мы думаем, что ObservedObject приводит к повторному рендерингу представления, но не к повторному созданию экземпляра, поэтому ViewModel остается прежним. Теперь мы заменили NavigationView на библиотека, который работает для нас, но нам все еще любопытно, можно ли исправить это поведение.

Philipp Fahlteich 08.04.2021 14:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
37
0

Другие вопросы по теме