Создание управляемого объекта в SwiftUI NaviagationLink - PullRequest
1 голос
/ 08 апреля 2020

Я хочу использовать довольно сложное представление для обновления и создания управляемых объектов CoreData.
Чтобы сделать код короче, представление редактирования / создания здесь сокращено.

В случае создания нового Person моя проблема заключается в том, когда создавать экземпляр NSManagedObject.

Приведенный ниже код дает сбой в Варианте 1. Похоже, представление Edit в NavigationLink имеет вид вызывается до того, как будет выполнено действие кнопки, которая создает объект.

Другой подход, который я пробовал, заключался в создании объекта в параметре NavigationLink (вариант 2).
Здесь у меня довольно странный вид, что при изменении задания на manager редактирование просмотра прекращается без нажатия кнопки.

Какой подход вы бы порекомендовали?

struct ContentView: View {
  @FetchRequest( entity: Person.entity(), sortDescriptors: [],
                 predicate: NSPredicate(format: "job ='manager'"))             
  var persons: FetchedResults<Person>
  @State var newPerson : Person?
  @State var selection: Int? = nil

  @Environment(\.managedObjectContext) var moc

  var body: some View {
    NavigationView {
      VStack{
        Text("\(persons.count) persons")
        List(persons, id: \.self) { person in
          HStack {
            NavigationLink(destination: Edit(person: person)) {
              HStack {
                Text("\(person.name) -- \(person.job )")
              }
              Image(systemName: "trash").onTapGesture {
                self.moc.delete(person)
                try! self.moc.save()
              }
            }
          }
        }
        /*  Variante 1 */
        NavigationLink(destination: Edit(person: self.newPerson!, new: true), tag: 1, selection: $selection) {
          Button(action: {
              print("login tapped")
              self.selection = 1
              self.newPerson = Person(context: self.moc)
              self.newPerson?.job = "manager"
              try! self.moc.save()
          }) {
            Text("New Person V1").bold()
          }
        }

        /* Variant 2
        NavigationLink(destination: Edit(person: Person(context: self.moc), new: true)) {
          Text("New Person V2").bold()
        }
        */
      }
    }
  }
}

struct Edit: View {
  @ObservedObject var person : Person
  var new = false
  @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
  @Environment(\.managedObjectContext) var moc

  var body: some View {
    VStack{
      TextField("Name", text: $person.name)
      TextField("Job", text: $person.job)
      Spacer()
      Button("Save"){
        do {
          try self.moc.save()
        } catch {
          print(error)
        }
        print("====================SAVE PRESSED")
        self.presentationMode.wrappedValue.dismiss()
      }
      Button("Cancel"){
        print("====================CANCEL PRESSED")
        self.moc.refresh(self.person, mergeChanges: false)
        self.presentationMode.wrappedValue.dismiss()
      }
    }
    .navigationBarTitle("\(self.new ? "New" : "Edit")")
    .navigationBarBackButtonHidden(true)
  }
}

What approach would you recommend?

1 Ответ

1 голос
/ 08 апреля 2020

Здесь возможна модификация Variant1 (выглядит более подходящей для go). Идея состоит в том, чтобы скрыть навигационную ссылку и сделать ее активной только по нажатию кнопки. Также сделайте пункт назначения условным, чтобы избежать раннего создания Edit представления.

См. Также встроенные комментарии.

  Button(action: {
      print("login tapped")
      self.newPerson = Person(context: self.moc)
      self.newPerson?.job = "manager"
      try! self.moc.save()

      self.selection = 1 // activate link at the end !!
  }) {
    Text("New Person V1").bold()
  }
  .background(NavigationLink(destination:
        Group {    // safe variant, can be separated into computed property
            if self.newPerson != nil {
                Edit(person: self.newPerson!, new: true)
            } else { EmptyView() }
        },
        tag: 1, selection: $selection) { EmptyView() })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...