为什么我们可以使用NSManagedObjectContext而不在CoreData中设置其persistentStoreCoordinator

时间:2015-11-06 06:26:16

标签: ios core-data

上下文的正常初始化是这样的:

lazy var context : NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.coordinator
return context
}()

但为什么我可以用这种方式初始化上下文:

var managedObjectContext : NSManagedObjectContext?
lazy var note: Note? = {
if let context = self.managedObjectContext {
  return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
}
return .None
}()

如果我没有设置persistentStoreCoordinator,那么上下文将以哪种方式存储实体。顺便说一下,这不是在demo中创建的第一个上下文,它只是一个名为Node的manageredobject的上下文

在线等待..........

整个代码是:

import UIKit

import CoreData

class CreateNoteViewController : UIViewController, UITextFieldDelegate, UITextViewDelegate {
 var managedObjectContext : NSManagedObjectContext?
  lazy var note: Note? = {
   if let context = self.managedObjectContext {
        return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
}
return .None
}()

  @IBOutlet var titleField : UITextField!
  @IBOutlet var bodyField : UITextView!
  @IBOutlet var attachPhotoButton : UIButton!
  @IBOutlet var attachedPhoto : UIImageView!

   override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if let image = note?.image {
  attachedPhoto.image = image
  view.endEditing(true)
} else {
  titleField.becomeFirstResponder()
}
 }


   @IBAction func saveNote() {
  note?.title = titleField.text
  note?.body = bodyField.text

  if let managedObjectContext = managedObjectContext {
  do {
  try  managedObjectContext.save()
}
  catch let error as NSError {
print("Error saving \(error)", terminator: "")
  }
  }
  performSegueWithIdentifier("unwindToNotesList", sender: self)
 }

  func textFieldShouldReturn(textField: UITextField) -> Bool {
    saveNote()
    textField.resignFirstResponder()
    return false
  }

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "AttachPhoto" {
if let nextViewController = segue.destinationViewController as? AttachPhotoViewController {
nextViewController.note = note
}
    }
  }
   }

viewcontroller的功能是从本地闹钟中选择一张照片,并保存标题,节点用于保存所有信息,所以作者确实使用了默认上下文(即使我不知道为什么他不使用默认上下文),他初始化一个新的上下文来保存节点,甚至没有设置任何东西,它的惊人,甚至是他没有设置的文件路径的路径,  我将告诉你默认的堆栈:

     import Foundation
      import CoreData

     class CoreDataStack: CustomStringConvertible {
       var modelName : String
       var storeName : String
       var options : [String : AnyObject]?

        init(modelName:String, storeName:String, options: [String : AnyObject]? = nil) {
self.modelName = modelName
self.storeName = storeName
self.options = options
      }

         var description : String {
return "context: \(context)\n" +
  "modelName: \(modelName)" +
  "storeURL: \(storeURL)\n"
       }

  var modelURL : NSURL {
return NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")!
   }

    var storeURL : NSURL {
var storePaths = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory, .UserDomainMask, true) as [String]
let storePath = String(storePaths[0]) as NSString
let fileManager = NSFileManager.defaultManager()

do {
  try fileManager.createDirectoryAtPath(storePath as String, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
  print("Error creating storePath \(storePath): \(error)")
}
let sqliteFilePath = storePath.stringByAppendingPathComponent(storeName + ".sqlite")
return NSURL(fileURLWithPath: sqliteFilePath)
        }

         lazy var model : NSManagedObjectModel = NSManagedObjectModel(contentsOfURL: self.modelURL)!

          var store : NSPersistentStore?

               lazy var coordinator : NSPersistentStoreCoordinator = {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.model)
do {
  self.store = try coordinator.addPersistentStoreWithType(
    NSSQLiteStoreType,
    configuration: nil,
    URL: self.storeURL,
    options: self.options)
} catch var error as NSError {
  print("Store Error: \(error)")
  self.store = nil
} catch {
  fatalError()
}
return coordinator
     }()

             lazy var context : NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.coordinator
return context
       }()
    }

2 个答案:

答案 0 :(得分:0)

您的第一个代码段创建了一个托管对象上下文:

lazy var context : NSManagedObjectContext = {
    let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    context.persistentStoreCoordinator = self.coordinator
    return context
}()

您的第二个代码段无法创建托管对象上下文:

var managedObjectContext : NSManagedObjectContext?
lazy var note: Note? = {
    if let context = self.managedObjectContext {
        return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
    }
    return .None
}()

第二个片段使用Swift可选展开来检查self.managedObjectContext是否为零。如果它不是,则将其分配给局部变量context。您不必在此处设置持久性存储协调器,因为您没有创建托管对象上下文。此代码假定self.managedObjectContext已在其他位置创建(可能在第一个代码段中)。

如果没有持久性存储协调器,托管对象上下文就没有多大用处,您无法对其进行任何有用的操作。您尤其无法使用它保存数据。但由于您的第二个代码段并未创建托管对象上下文,因此这并不重要。

答案 1 :(得分:0)

协调器不是init方法的参数有很多可能的原因。

由于上下文可以与商店协调器或父上下文一起使用,因此在每种情况下还包括并发类型param的init方法将很麻烦,并使子类化更加棘手。因此,他们选择了一次设置一次属性,即,如果再次设置它们,则会出现不一致情况,即“上下文已具有协调器;无法替换。”。

允许在准备使用上下文之前创建上下文,这为应用程序的初始化例程提供了更大的灵活性。首先,在创建堆栈的各个部分,模型,协调器,上下文等方面提供了灵活性。其次,可以先将上下文传递给视图控制器,然后再将存储加载并在上下文上设置协调器。并且viewController可以侦听NSPersistentStoreCoordinatorStoresDidChangeNotification,然后检查上下文是否现在具有有效的协调器,然后执行其视图更新。