核心数据:使用新创建的ManagedObject来详细说明控制器

时间:2017-06-12 09:19:37

标签: ios objective-c swift uitableview core-data

场合

  1. 用户点击按钮将项目添加到表格视图。
  2. 表视图控制器添加项目并直接segue到编辑/详细信息视图控制器。
  3. 项目是使用NSFetchedResultsController填充的核心数据对象。

    问题

    如何获得对新对象的有效引用,以便我可以执行segue?我正在寻找共同的模式,而不是违反任何核心数据规则。

    代码

    class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate {
      var context: NSManagedObjectContext!
      var frc: NSFetchedResultsController!  // set up fetch request etc.
    
      // User initiated
      func addItem(_ sender: Any) {
        context.perform {
          let item = Item(context: context)
          try! context.save()
        }
    
        // How to get hold of the new item and where to initiate the segue?
      }
    
      func prepare(for segue: UIStoryboardSegue, sender: Any) {
        // Pass new item to detail view controller
      }
    
      // NSFetchedResultsControllerDelegate methods
      // refresh table on updates
    }
    

    思想

    1)假设context是主视图上下文,这是安全和正确的吗?

    var newItem: Item?
    
    func addItem(_ sender: Any) {
      context.perform {
        newItem = Item(context: context)
        try! context.save()  // error handling etc.
        performSegue(...) 
      }
    }
    
    func prepare(for segue: UIStoryboardSegue, sender: Any) {
      // ...
      detailController.item = newItem
    }
    

    执行块将在上下文队列中执行,该队列是主队列,它会使对象从闭包中抓取并使segue安全,对吗?

    2)或者这个?

    context.performAndWait {
      newItem = Item(context: context)
      try! context.save()
    }
    
    performSegue(...) 
    

    对于 1) 2):如果这不是主要背景怎么办?我能将对象转移到主线程/视图控制器吗?

    3)抓住FRC代表中的对象:

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
       // Assuming insert
       new Item = object
       performSegue(...)
    }
    

    我如何知道object是我刚刚插入的并想要与之相关的,而不仅仅是通过其他方式插入的某个对象?我可以确定当我插入一个对象时,下一次调用委托方法会引用该对象吗?可能存在插入元素的并行上下文......

    参考

    没有核心数据的基本设置我正在尝试重新创建:

    class MasterViewController: UITableViewController {
      var tableViewData = [Item]()
      let newItem: Item?
    
      // On user button press
      func addItem(_ sender: Any) {
        newItem = Item()
        tableViewData.append(newItem)
        tableView.reloadData()
        performSegue(withIdentifier: "showDetail")         
      }
    
      func prepare(for segue: UIStoryboardSegue, sender: Any) {
        // ...
        detailController.item = newItem
      }
    }
    

1 个答案:

答案 0 :(得分:2)

在我看来,这可能更清楚:

//On user button press
func addItem() { 
     performSegue(withIdentifier: "showDetail")
}

func prepare(for segue: UIStoryBoardSegue, sender: Any) {
    if segue.identifier == "showDetail" {
    //create the item(managedobject), save the context

    //feed the item to the destination viewcontroller who needs it
    }
}

通过这种方式,你知道你所使用的对象是正确的,你的逻辑就更紧密了。

参考背景。当您创建managedObjectContext时,您可以指定您将如何使用它(主要或私有),并且您必须坚持这一点。拥有一个上下文的最佳实践是传递视图控制器层次结构。

当您开始考虑将设备上的数据与后端数据库同步时,您可能需要第二个上下文,我认为情况并非如此。 也许,您需要将第二个上下文设置为专用队列,然后才需要担心将managedobjects映射到正确的上下文。

在此之前,您唯一的背景是非常友好的动物。