【发布时间】:2016-05-02 01:05:27
【问题描述】:
为了不埋没问题,我将打开我的核心问题:为什么我的 NSFetchedResultsController 的 fetchedObjects 数组通常是同质的,但在极少数情况下在它的托管对象中包含 __NSCFString应该包含?
我有一个应用程序已经投入生产很长时间了。它的主要视图是一个包含视频列表的表格视图,由核心数据托管对象支持。表视图控制器使用一个NSFetchedResultsController 配置一个相当普通的NSFetchRequest:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:[ABCVideo entityName]];
NSString *sectionKeyPath = nil;
request.fetchBatchSize = 20;
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:ABCVideoAttributes.recordingDate ascending:NO];
sectionKeyPath = @"sectionIdentifier";
request.sortDescriptors = @[sort];
request.predicate = [NSPredicate predicateWithFormat:@"owner = %@ and %K = %@", person, ABCVideoAttributes.serverDeleted, @(NO)];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:moc sectionNameKeyPath:sectionKeyPath cacheName:kABCMyVideosTableViewControllerCacheKey];
由于这些视频可以上传到云端,因此此表格视图控制器会偶尔收到通知,以更新与当前正在上传的视频相对应的表格视图单元格中的进度条。在这个回调中,我们获取NSFetchedResultsController的fetchedObjects数组来查找通知对应的视频,以便正确的表格视图单元格可以更新其进度条。
这一切都有效。 99.9% 的时间,它每次都有效</RonBurgundy>。
但我在我们的 HockeyApp 崩溃报告中注意到,当我的通知处理程序试图从 fetchedObjects 获取 filteredArrayUsingPredicate 时,我收到了一个 SIGABRT,这种情况非常罕见:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x136f24480> valueForUndefinedKey:]: this class is not key value coding-compliant for the key guid.'
最近我设法找到一个偶尔可以重现此崩溃的案例,经过大量实验后,我发现 fetchedObjects 数组有时包含不是 ABCVideo 的东西:相反,一个插槽该数组被__NSCFString 实例占用。考虑到NSFetchRequestResultType 属于NSManagedObjectResultType,并且字符串不是托管对象,这非常令人惊讶。
所以我想知道:这是核心数据错误吗?或者我的数组是否包含一个指针,该指针以前指向已释放的 ABCVideo 实例,而堆上的该位置随后被 __NSCFString 实例占用?如果是后者,那怎么会这样呢?我正在使用 ARC,因此很难理解其中一个视频是如何被释放的。
【问题讨论】:
-
我怀疑存在核心数据错误。 iOS9 引入了几个 bug,尤其是 NSFetchedResultsControllers,这可能是另一个。
-
数组本身应该保留它的对象,所以除非你以某种方式
releaseing one-too-many,否则它们不应该被释放。此外,对于 ARC,几乎可以肯定情况并非如此。可能是 ARC 错误或核心数据错误。你能排除这与NSFetchedResultsController的缓存有关吗?禁用缓存和重现? -
由于您可以重现它,因此检测何时发生这种情况并检查字符串的内容可能很有用。我不知道为什么字符串在那里,但它的内容可能指向一个原因。
-
很可能有一个指针曾经指向一个 NSManagedObject(子类),现在指向一个被 NSString 对象占用的内存位置。真正的问题是:你在哪里访问这个指针,为什么它不再指向一个 NSManagedObject?您是否正在跨线程使用此数组?你把自己的参考资料保存在某处吗?你能分享更多关于到底发生了什么吗?这对我来说似乎不是核心数据错误。
-
@JanGreve 设置每次复制尝试都需要一段时间,而且它不会每次都触发错误,但我能够设置 9 次尝试(5 次禁用缓存,4 次禁用缓存)启用缓存)。即使没有缓存,我也会崩溃,尽管它更改为 EXC_BAD_ACCESS 而不是上面的 SIGABRT。 (可悲的是,如果我启用僵尸对象,我根本无法重现问题。)
标签: ios objective-c core-data nsfetchedresultscontroller nsfetchrequest