在 SwiftUI NaviagationLink 中创建 ManagedObject

Posted

技术标签:

【中文标题】在 SwiftUI NaviagationLink 中创建 ManagedObject【英文标题】:Creating a ManagedObject in a SwiftUI NaviagationLink 【发布时间】:2020-04-08 07:44:11 【问题描述】:

我想使用一个相当复杂的视图来更新和创建 CoreData 托管对象。 为了使代码更短,此处的编辑/创建视图“编辑”被缩短。

在创建新Person的情况下,我的问题是,什么时候创建NSManagedObject Instance。

下面的代码在变体 1 中崩溃。似乎在执行创建对象的按钮操作之前调用了 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】:

这是对 Variant1 的可能修改(看起来更合适)。这个想法是隐藏导航链接并使其仅在单击按钮时才处于活动状态。还要使目标成为有条件的,以避免过早创建Edit 视图。

另见 cmets inline。

  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() )

【讨论】:

以上是关于在 SwiftUI NaviagationLink 中创建 ManagedObject的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 如何在 SwiftUI 中弹出到特定视图?

SwiftUI - SwiftUI 中是不是有等效的 popViewController?

SwiftUI - 在 SwiftUI 中对显示的 JSON 文件进行排序,分节或排序

如何在 SwiftUI 中使用 Realm

在 SwiftUI 中滑动列表时隐藏导航栏

如何在 SwiftUI 的 ScrollView 中制作动画? SwiftUI 中的手风琴风格动画