2017-04-05 100 views
0

核心数据的新特性和我有两个问题:正确初始化NSManagedObject,并保留其在便利和指定初始值设定项之间的值。初始化核心数据管理对象

我在我的AnalyticsEvent NSManagedObject子类代码:

@NSManaged public var eventName: String? 
@NSManaged public var type: String? 
@NSManaged public var reference: String? 
@NSManaged public var timestamp: Double 

public required init() { 

    // Initialize CoreData stack... 
    let manager = CoreDataManager(modelName: "Analytics", storeName: "Analytics") 

    // I'm not sure what I should be using to instantiate a new entity here... 
    // I believe the entity(forEntityName:in:) class method should return an existing value stored in managedObjectContext... 
    let event = NSEntityDescription.entity(forEntityName: "Event", in: manager.managedObjectContext!) 

    // ... and insertNewObject(forEntityName:into:) to create a placeholder 
    // for my new object until I issue saveContext() on managedObjectContext. 
    // This isn't working right now, so comment out following line 
    //let event = NSEntityDescription.insertNewObject(forEntityName: "Event", into: database.managedObjectContext!) as! AnalyticsEvent 
    super.init(entity: event!, insertInto: database.managedObjectContext) 

    let customProperties = CustomProperties() 
    self.customPropertiesData = NSKeyedArchiver.archivedData(withRootObject: properties) as Data 
    self.timestamp = Date().timeIntervalSince1970 
} 

public convenience init(eventName: String) { 
    self.init() 

    // At this point the data set in my designated initializer (above), 
    // the values have been lost. For example, timestamp == 0 
    self.eventName = eventName 
    self.type = EventType.discreteEvent 
} 

谢谢!

编辑:

进一步调查可能会发现,也许我的便利初始化正在被super.init(entity:insertInto:)调用来调用,如果是,我不知道它是怎么找到的便利初始化的选择...但它会解释为什么它的值(如时间戳)没有被保留 - 因为它是对象的新实例?!嗯......

编辑2:

我忘了说我得到这个运行时错误当执行到行:

self.eventName = eventName 

CoreData:错误:变异托管对象0x7fa2da54da90(0x7fa2da54da40 )在它从上下文中移除之后。

回答

0

认为这里发生了什么是你需要做init()也便利初始化,并调用self.init(entity: event!, insertInto: database.managedObjectContext)(而不是super)内。

编辑:我今天试着创建一个最小的工作示例,并没有得到一个错误,今天又看了一遍。

我用一个单一的实体是一个User,仅仅有一个名字property工作:

import Foundation 
import CoreData 

@objc(User) 
public class User: NSManagedObject { 

    @nonobjc public class func fetchRequest() -> NSFetchRequest<User> { 
     return NSFetchRequest<User>(entityName: "User") 
    } 

    @NSManaged public var name: String? 

    convenience init() { 
     let context = CoreDataManager.shared.persistentContainer.viewContext 
     self.init(context: context) 
     self.name = "Mathew" 
    } 

    convenience init(named name: String) { 
     self.init() 
     self.name = name 
    } 
} 

CoreDataManager仅仅是自动生成的代码,Xcode的,但移动到它自己的对象:

import Foundation 
import CoreData 

class CoreDataManager { 

    static let shared = CoreDataManager() 

    lazy var persistentContainer: NSPersistentContainer = { 
     let container = NSPersistentContainer(name: "CoreDataInit") 
     container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
      if let error = error as NSError? { 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     }) 
     return container 
    }() 

    func saveContext() { 
     let context = persistentContainer.viewContext 
     if context.hasChanges { 
      do { 
       try context.save() 
      } catch { 
       let nserror = error as NSError 
       fatalError("Unresolved error \(nserror), \(nserror.userInfo)") 
      } 
     } 
    } 
} 

当我尝试测试这个,我得到预期的行为:

_ = User() 
_ = User(named: "Marge") 
_ = User(named: "Homer") 

let fetchUsers: NSFetchRequest<User> = User.fetchRequest() 

if let results = try? CoreDataManager.shared.persistentContainer.viewContext.fetch(fetchUsers) { 
print("there are", results.count, "users") 

for user in results { 
    print("user is", user.name!) 
} 

// prints: 
// Mathew 
// Marge 
// Homer 

但是,在User类中,当我从单例转移到创建例如CoreDataManager的新实例时,

//let context = CoreDataManager.shared.persistentContainer.viewContext 
let context = CoreDataManager().persistentContainer.viewContext 

这一变化引发了“CoreData:错误:变异的管理对象后,它已被从上下文中删除。”错误。

所以我第二次诊断你的错误是它来自不使用相同的持久性存储协调器(以及不同的上下文)。

如果持久性存储可以配置(例如,为了传递模型的名称),那么我认为最好转换到初始化程序,这似乎是更常见的CoreData模式。

排序一个漫无边际的答案,但希望这一次它不是一个红鲱鱼!

+0

谢谢,但我也试过。没有运气!它也提供相同的运行时错误。 –

+0

@AlexSmith我正在研究初始化器和'@ NSManaged'实际上现在意味着什么...你见过这个答案:http://stackoverflow.com/a/39239651/1060154我不能担保它,但会快速尝试! – MathewS

+0

再次感谢,但不幸的是不是我所需要的。和以前一样... –