为什么我不能在传递参数时初始化我的NSManagedObject?

时间:2017-05-18 02:42:31

标签: swift core-data initialization

我的应用程序中有一个类(Swift 3),它包含我从AppDelegate移出的基本CoreData堆栈。应用程序需要执行的所有操作都在我调用CoreDataHelper的另一个类中。当应用程序启动时,AppDelegate会创建一个CoreDataHelper(let dataManager = CoreDataHelper())的实例,这是与堆栈对话的唯一内容。然后在launchCalculatorViewController()中,dataManager向堆栈询问新的LiftEvent

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    let dataManager = CoreDataHelper()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // check if data needs to be loaded and load it if needed...

      launchCalculatorViewController()    
      return true
    }

    func launchCalculatorViewController() {
      self.window = UIWindow(frame: UIScreen.main.bounds)
      let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
      if let initialViewController: CalculatorViewController = mainStoryboard.instantiateInitialViewController() as? CalculatorViewController {

      // create the liftEvent, the viewModel, and wire it up to the view controller
      let liftEvent = dataManager.createNewLiftEvent() // go get me a new LiftEvent
      let viewModel = calculatorLiftEventViewModelFromLiftEvent(withLiftEvent: liftEvent, dataManager: dataManager)
      initialViewController.viewModel = viewModel
      initialViewController.dataManager = dataManager

      self.window?.rootViewController = initialViewController
      self.window?.makeKeyAndVisible()
    }
}

这是createNewLiftEvent()中的dataManager方法:

func createNewLiftEvent() -> LiftEvent {
    let newLiftEvent = LiftEvent(dataManager: self, insertIntoManagedObjectContext: stack.managedObjectContext)

    return newLiftEvent
}

并且LiftEvent的初始化如下所示:

class LiftEvent: NSManagedObject, LiftEventProtocol {

    var dataManager: CoreDataHelper!

    override func awakeFromInsert() {
        super.awakeFromInsert()

        let date = Date()
        self.date = date

        let defaultUnit = UserDefaults.weightUnit()

        if defaultUnit == "kg" {
            weight = Measurement(value: 0.0, unit: .kilograms)
            liftWeights[defaultUnit] = weight
        } else {
            weight = Measurement(value: 0.0, unit: .pounds)
            liftWeights[defaultUnit] = weight
        }

        if let defaultFormula = dataManager.fetchDefaultFormula() { // unexpected nil error thrown here
            self.formula = defaultFormula // this is an NSManagedObject 
        }                                 
    }

    convenience init(dataManager: CoreDataHelper, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
        let entity = NSEntityDescription.entity(forEntityName: "LiftEvent", in: context)!
        self.init(entity: entity, insertInto: context) // exits after this line
        self.dataManager = dataManager // never gets executed so of course it's nil
    }
}

我在解开Option值时出现“意外发现的nil”错误,因为此时dataManager为nil。我尝试在便捷初始化程序中设置它,但self.dataManager = dataManager从未执行,因为它在self.init之后立即退出。当然我不能把它放在self.init之前,因为在设置值之前对象必须存在。

我正在尝试传递dataManager以确保正在创建的公式(也是NSManagedObject)和新的LiftEvent位于同一个托管对象上下文中所以我可以在awakeFromInsert()中设置它们之间的关系。在尝试这种方法之前它崩溃了,因为LiftEventFormula是两个不同的managedObjectContexts(尽管我做了很多工作以确保dataManager和堆栈只被实例化一次)。上面的方法受到this thread的启发,但我想我可能不理解初始化以及我认为我做过。

如何传入托管对象上下文以创建LiftEvent,因此它与Formula位于同一个托管对象上下文中,因此可以设置关系?或者,这是完全错误的方法吗?

0 个答案:

没有答案