SwiftUI: как открыть детальный вид после удаления его модели - PullRequest
0 голосов
/ 05 февраля 2020

Рассмотрим довольно простое приложение SwiftUI: представление списка, показывающее список моделей, где каждая строка представляет собой NavigationLink для подробного представления. С SwiftUI любые изменения в текущей модели просмотра автоматически приводят к обновлению пользовательского интерфейса; В подробном представлении всегда отображается последняя версия модели. Ура! :)

Но как быть с удалением модели, когда вы находитесь в подробном представлении? Это ничего не делает, вы остаетесь в подробном представлении. Ниже приведен очень простой пример, иллюстрирующий проблему:

struct Model: Identifiable {
  let id: Int
  var title: String
}

class Store: ObservableObject {
  @Published var models = [Model(id: 0, title: "a")]
}

struct ListView: View {
  @EnvironmentObject private var store: Store

  var body: some View {
    NavigationView {
      List(store.models) { model in
        NavigationLink(destination: DetailView(model: model)) {
          Text(model.title)
        }
      }
      .navigationBarTitle("List")
    }
  }
}

struct DetailView: View {
  @EnvironmentObject private var store: Store

  var model: Model

  var body: some View {
    Text(model.title)
      .navigationBarTitle("Detail")
      .navigationBarItems(trailing: trailingNavigationBarItems)
  }

  private var trailingNavigationBarItems: some View {
    HStack {
      Button("Change title") {
        self.store.models[0].title = "AAA"
      }

      Button("Delete model") {
        self.store.models.remove(at: 0)
      }
    }
  }
}

Как детальный вид распознает, что его модель больше не существует, и вернется к представлению списка? Как я уже сказал, в данный момент вы просто находитесь в подробном представлении, глядя на модель, которой на самом деле больше не существует. Когда вы вручную go вернетесь к списку, он обновится, и модель исчезнет.

Если вы хотите запустить этот код, просто используйте ListView().environmentObject(Store()) в качестве rootView в SceneDelegate.

(Прежде чем кто-либо скажет, что я могу просто вернуться к действию кнопки удаления, эта кнопка как раз там, чтобы продемонстрировать проблему. В действительности модель может быть удалена, например, на сервере, а не действием, инициированным из детали. вид.)

1 Ответ

1 голос
/ 05 февраля 2020

Я бы решил эту проблему следующим образом. Например, если я хочу узнать, не содержит ли модель содержимого, я автоматически go вернусь к представлению списка, программно отобразив текущее представление. И это работает.

struct DetailView: View {
  @EnvironmentObject private var store: Store
  @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

  var model: Model

  var body: some View {
    ZStack {
        Text(model.title)
    }
    .navigationBarTitle("Detail")
    .navigationBarItems(trailing: trailingNavigationBarItems)
    .onReceive(self.store.$models) { model in
        if model.count == 0 {
            self.presentationMode.wrappedValue.dismiss()
        }
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...