如何在 MVVM 模式中设置托管对象之间的关系?

How do set a relationship between managed objects within an MVVM pattern?

我正在构建一个应用程序并尝试使用 MVVM 模式。虽然有大量关于如何连接数据以从模型到视图模型到控制器再到视图的信息,但我很难学习如何在坚持 MVVM 原则的同时做其他事情.我真正苦苦挣扎的一件事是在转到不同的视图控制器后设置两个托管对象之间的关系。让我解释一下...

当我的应用程序启动时,它会显示第一个视图控制器,它由一个视图模型支持,该视图模型与新创建的 NSManagedObject 类型 LiftEvent 对话。从这里,用户可以转到也有视图模型的设置视图控制器,从那里他们可以转到也有视图模型的 table 视图,并进行需要更改的选择NSManaged var 属性 模型对象。这个 属性 是与另一个 NSManagedObject 的关系。流程如下:

我正在将 managedObjectContext 从第一个视图控制器传递到设置视图控制器:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
   if let nav = segue.destinationViewController as? UINavigationController {
     let vc = nav.topViewController as! SettingsViewController
     vc.dismissalDelegate = self

     let moc = viewModel.model.context
     vc.moc = moc
   }

然后再次传递给最后一个视图控制器,用户在其中进行选择,我想设置关系。它有效,但我不喜欢它,因为我现在必须在我传递给它的视图控制器中 import CoreData

最右边的视图控制器是UITableViewController。当用户选择其中一行时,我想使用该选择来获取相应的托管对象并将其设置为应用程序启动时创建的对象的属性之一。这是 didSelectRowAtIndexPath 方法:

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    let defaultFormula = NSUserDefaults.formula()
    guard indexPath.row != defaultFormula.rawValue else { return }

    if let newDefaultFormula = FormulaName(rawValue: indexPath.row) {
        NSUserDefaults.setDefaultFormulaName(newDefaultFormula)
    }

    if let selectedFormula = formulasArray[indexPath.row] {
       // now what? 
    }
  }

FormulaName 是可能名称的枚举。数据源是 formulasArray,一个 Formula 托管对象的数组。我在 viewDidLoad 中初始化数组:

  override func viewDidLoad() {
    super.viewDidLoad()

    formulasArray = dataManager.fetchSelectableFormulas(moc)
  }

我在脑海中看到了一些可能的解决方案,但我不知道其中哪一个(如果有的话)是不错的选择:

  1. 将我从数组中挑选出来的公式对象传递回 unwind segues 中的第一个视图控制器并在那里设置关系
  2. 以某种方式从这里获取 LiftEvent,设置关系,然后告诉第一个视图控制器的视图模型对象已更改。
  3. 传递对 LiftEvent 对象的引用,而不是仅传递 managedObjectContext 属性

我花了无数个小时试图找到示例、课程、git 存储库、SO 线程等来弄清楚我不知道从这里去哪里。我没有要求任何人为我编写代码,只是引导我朝着好的方向前进,我将永远感激不已。

我在 iOS 中找到 MVVM 的具体示例时也遇到了问题,所以我开发了自己的方法。

我有几个建议(这是要明确的意见)。

  1. 将 NSManagedObject 上下文保存在 CD 访问单例中,以便在主线程上访问非常有用。假设您没有使用多个数据库或在后台做一堆事情(如果需要,您也可以使用访问器处理)您将有 1 个没有上下文传递的上下文。

  2. 使用 Segues 时,依赖注入非常棒。无需为您的新 VC 提供查找数据和设置所需的最少信息,只需在 Segue 中设置它的 ViewModel 并构建 VC 以仅以此为基础工作。这就是 ViewModel 如此出色的原因。您的View/ViewController不需要知道关于您的模型的任何信息

在处理平仓时,我的方法是简单地在所需的 VC 中创建一个 "selectedItem" 属性 并将做什么的责任留给 VC它正在展开。如有必要,它可以在展开时获取该值。这允许您选择 VC 以相同的方式操作,而不管周围的行为如何。