2017-04-05 7 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()을해야하고, (오히려 super 이상)이 호출 self.init(entity: event!, insertInto: database.managedObjectContext) 내 것입니다.

편집 : 오늘은 최소한의 작업 예제를 만들려고 시도하면서 오류가 발생하지 않았습니다. 단순히 이름 property있는 User 단일 엔티티로 일하고 있어요

:

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)") 
      } 
     } 
    } 
} 
:

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은 엑스 코드는하지만 자신의 객체로 이동 바로 자동 생성 된 코드

테스트 할 때 예상되는 동작이 발생합니다.

_ = 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 : error : 컨텍스트에서 관리 대상 개체가 제거 된 후 Mutating'이 트리거되었습니다. 오류.

두 번째 진단은 동일한 영구 저장소 코디네이터를 사용하지 않아서 발생한다는 것입니다 (다른 문맥도 마찬가지입니다).

영구 저장소를 구성 할 수 있어야하는 경우 (예 :모델의 이름을 전달하려면) 컨텍스트 내에서 일반적인 CoreData 패턴보다 많은 것으로 보이는 NSManagedObject 이니셜 라이저로 전달하는 것이 더 나을 것이라고 생각합니다.

소름 끼치게 대답하지만, 이번에는 청어 청어가 아니길 바랍니다.

+0

감사하지만이 역시 시도했습니다. 불운! 동일한 런타임 오류도 제공합니다. –

+0

@AlexSmith 나는 이니셜 라이저를 파고 있는데 무엇이'@ NSManaged'가 실제로 의미하는지 ...이 답변을 본 적이 있습니까 : http://stackoverflow.com/a/39239651/1060154 나는 그것을 보증 할 수는 없지만 빠른 시도! – MathewS

+0

다시 한 번 감사드립니다.하지만 불행히도 내가 필요한 것은 아닙니다. 이전과 같음 ... –