cocoa - 核心数据中存在看似有效对象的 "Dangling reference to an invalid object"错误

标签 cocoa core-data

我在使用 Core Data 时遇到了一个非常令人困惑的问题。在我的核心数据存储中,对于现有的核心数据对象,我检查是否存在关系,如果不存在,我将像这样创建对象(这是 AFFingerprintGeneratorOperation 上的方法):

NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] init];
[newContext setMergePolicy:NSOverwriteMergePolicy];
NSPersistentStoreCoordinator *sharedStoreCoordinator = [[AFMainController sharedInstance] persistentStoreCoordinator];
[newContext setPersistentStoreCoordinator:sharedStoreCoordinator];
[self setManagedObjectContext:newContext];  // retaining property
[newContext release];

NSEntityDescription *fetchedTagSetEntity = [NSEntityDescription entityForName:@"FetchedTagSet"
                                                       inManagedObjectContext:newContext
                                            ];

AFTrack *retrievedTrack = (AFTrack *)[newContext objectWithID:[self trackObjectID]];
[self setTrack:retrievedTrack];

if (! retrievedTrack.fetchedTagSet) {
    AFFetchedTagSet *newFetchedTagSet = [[AFFetchedTagSet alloc] initWithEntity:fetchedTagSetEntity
                                                 insertIntoManagedObjectContext:newContext];

    [[retrievedTrack storedTrack] setFetchedTagSet:newFetchedTagSet];
    [newFetchedTagSet setStoredTrack:[retrievedTrack storedTrack]];
}

AFTrack、AFetchedTagSet 和 AFStoredTrack 都是核心数据对象。 AFFetchedTagSet 和 AFStoredTrack 位于磁盘上的核心数据存储中,而 AFTrack 位于单独的内存中核心数据存储中。

请注意,由于 AFStoredTrack 对象位于单独的存储中,因此我需要像这样获取它(这是 AFTrack 上的方法):

NSManagedObjectContext *objectContext = [self managedObjectContext];
NSPersistentStoreCoordinator *coordinator = [objectContext persistentStoreCoordinator];
NSString *URIString = [self storedTrackObjectIDString];

AFStoredTrack *theStoredTrack = nil;
if (URIString) {
    NSURL *objectURL = [NSURL URLWithString:URIString];
    NSManagedObjectID *storedTrackObjectID = [coordinator managedObjectIDForURIRepresentation:objectURL];
    theStoredTrack = (AFStoredTrack *)[objectContext objectWithID:storedTrackObjectID];
}

return theStoredTrack;

由于这是 AFTrack 上的一个方法,它只是检索 AFTrack 自己的托管对象上下文,因此第一个摘录中的代码应始终对所有操作使用完全相同的托管对象上下文。

但是,在第一个摘录中,在使用新对象调用 setFetchedTagSet: 并尝试保存核心数据存储后,我收到此错误:

"Dangling reference to an invalid object." = "<null>";
NSAffectedObjectsErrorKey =     (
    "<AFStoredTrack: 0x11550eef0> (entity: StoredTrack; id: 0x101eb57d0 <x-coredata:///StoredTrack/tF7F5568E-2959-4786-B73D-B7AC6586F5B9121> ; data: {\n    fetchedTagSet = \"0x11c956b60 <x-coredata:///FetchedTagSet/tF7F5568E-2959-4786-B73D-B7AC6586F5B9124>\";\n    fingerprint = \"ASPtPiNHPC7fGSYXTxtfFboMCg7BCxYQ+gZRCL4FWQdzBD8HPw\";\n    persistentID = nil;\n    status = 3;\n    updateAlbumName = nil;\n    updateArtistName = nil;\n    updateArtwork = nil;\n    updateGenre = nil;\n    updateLyrics = nil;\n    updateReleaseYear = nil;\n    updateTrackName = nil;\n})"
);
NSLocalizedDescription = "storedTrack is not valid.";
NSValidationErrorKey = storedTrack;
NSValidationErrorObject = "<AFFetchedTagSet: 0x11c956ac0> (entity: FetchedTagSet; id: 0x11c956b60 <x-coredata:///FetchedTagSet/tF7F5568E-2959-4786-B73D-B7AC6586F5B9124> ; data: {\n    ampliFindPUID = nil;\n    fingerprint = nil;\n    matchAlbum = nil;\n    matchLyrics = nil;\n    matchTrackName = nil;\n    matchTrackNumber = 0;\n    storedTrack = \"0x101eb57d0 <x-coredata:///StoredTrack/tF7F5568E-2959-4786-B73D-B7AC6586F5B9121>\";\n})";
NSValidationErrorValue = "<AFStoredTrack: 0x11550eef0> (entity: StoredTrack; id: 0x101eb57d0 <x-coredata:///StoredTrack/tF7F5568E-2959-4786-B73D-B7AC6586F5B9121> ; data: {\n    fetchedTagSet = \"0x11c956b60 <x-coredata:///FetchedTagSet/tF7F5568E-2959-4786-B73D-B7AC6586F5B9124>\";\n    fingerprint = \"ASPtPiNHPC7fGSYXTxtfFboMCg7BCxYQ+gZRCL4FWQdzBD8HPw\";\n    persistentID = nil;\n    status = 3;\n    updateAlbumName = nil;\n    updateArtistName = nil;\n    updateArtwork = nil;\n    updateGenre = nil;\n    updateLyrics = nil;\n    updateReleaseYear = nil;\n    updateTrackName = nil;\n})";

但是 AFFetchedTagSet 和 AFStoredTrack 对象似乎都是有效的,因为它们的 ID 匹配,并且这些对象的对象上下文仍然存在并由 AFFingerprintGeneratorOperation 对象保留。

我见过这个CoreData: "Dangling reference to an invalid object." error还有这个http://lists.apple.com/archives/cocoa-dev/2009/Nov/msg00190.html ,但这两个链接似乎都没有帮助。前者似乎说关系不好(我认为不是),后者说避免改变 awakeFromFetch 中的关系,据我所知我没有这样做。

有什么帮助吗?

最佳答案

在本例中,Core Data 抛出的错误代码实际上非常正确,但很难弄清楚发生了什么。

AFTrack 对象上的“fetchedTagSet”属性只是 AFStoredTrack 上“fetchedTagSet”属性的一个方便的只读属性,这意味着为了检索 AFFetchedTagSet 类,我必须首先检索 AFStoredTrack 对象。

AFTrack 上获取 AFStoredTrack 方法的方法使用的是 objectRegisteredForID: 方法。如果对象未在您调用 objectRegisteredForID: 方法的托管对象上下文中注册,则不会获取对象。因此,我正在检索不存在的 AFStoredTrack 错误,并为其设置属性。

(注意:“未向托管对象上下文注册”并不意味着它们不存在于核心数据存储中。它只是意味着该特定托管对象上下文不存在还不知道该对象,因为您还没有在该上下文中插入或提取它。)

出于某种原因,objectRegisteredForID: 返回一个空白 AFStoredTrack,而不是文档所述的 nil。结果是我以为我有一个有效的 AFStoredTrack 对象,但实际上它只是一个占位符,所有值都为零。尝试保存对象使上下文意识到 AFSstoredTrack 无效,从而产生错误消息。

修复方法是将 AFTrack(检索 AFStoredTrack 对象的方法)上的方法更改为使用 objectWithID: 而不是 objectRegisteredForID: 。正如文档所述,objectWithID:如果上下文尚不知道该对象,则获取该对象。返回了一个有效的对象,然后一切正常。

关于cocoa - 核心数据中存在看似有效对象的 "Dangling reference to an invalid object"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3983555/

相关文章:

cocoa - 为什么我的新 subview 叠加在我的分割 View 中?

swift - 避免重复属性方法

ios - 魔法记录 CoreData 迁移问题

iphone - iPhone 上 sqlite 和核心数据的速度问题

cocoa - 核心数据: multiple entities related to a single entity

ios - 不同 View Controller 中的 NSFetchedResultsController 相互更新?

objective-c - GCD 等待队列中的所有任务完成

objective-c - 管理多个异步 NSURLConnection 连接

cocoa - 获取桌面上图标的位置

objective-c - UIManagedDocument 上的 saveToURL 核心数据失败