And*_*rew 2 iphone core-data objective-c ios
我不知道如何解决这个问题.每次用户滚动时,此代码都会在每个单元格中运行,并在UITableView中显示:
self.isFinishedProcessing = NO;
[self setNeedsDisplay];
[self.mediaArray removeAllObjects];
self.mediaArray = [[NSMutableArray alloc] init];
dispatch_queue_t queue = dispatch_queue_create("setup_cell", NULL);
NSManagedObjectID *objectID = [self.entry objectID];
dispatch_async(queue, ^{
CoreDataStore *customStore = [CoreDataStore createStore];
Entry *entry = (Entry *)[customStore.context objectWithID:objectID];
if (self.cellInfo.numberOfMediaItems > 0) {
int i = 0;
int numberOfThumbnails = MIN(self.cellInfo.numberOfMediaItems, 3);
while (i < numberOfThumbnails) {
Media *media = [entry.media objectAtIndex:i];
UIImage *image = [media getThumbnail];
[self.mediaArray addObject:image];
i++;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
self.isFinishedProcessing = YES;
[self setNeedsDisplay];
});
});
Run Code Online (Sandbox Code Playgroud)
核心数据存储采用Entry(核心数据类)和Media,并将其置于自己的上下文中.
我还没有弄清楚滚动时这个代码崩溃的确切时间,但是在向上和向下滚动几次时会发生这种情况.
编辑:在'索引对象'之前的NSLog说有一个计数3.我实际上做了entry.media.count,当然.
这是完整的错误:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
Run Code Online (Sandbox Code Playgroud)
编辑2:
还没有解决这个问题.我最后添加了这个:
if (self.mediaArray.count != self.entry.media.count) {
NSLog(@"INCORRECT BECAUSE.... media array count: %i, entry media count: %i number of media items: %i", self.mediaArray.count, self.entry.media.count, self.cellInfo.numberOfMediaItems);
}
Run Code Online (Sandbox Code Playgroud)
它经常在一个像这样的单元格之后崩溃:
INCORRECT BECAUSE.... media array count: 1, entry media count: 3 number of media items: 3
Run Code Online (Sandbox Code Playgroud)
如果它依赖于self.cellInfo.numberOfMediaItems创建,则不确定媒体数组计数可能是错误的.
另外值得注意的是,只有在单独的线程中完成时才会发生这种情况.永远不会在主线程中崩溃.
您违反了多个线程的Core Data 规则#1.
除非在该线程中创建了MOC,否则不得在线程中使用MOC.
你创建一个队列来为你运行一些工作......
dispatch_queue_t queue = dispatch_queue_create("setup_cell", NULL);
Run Code Online (Sandbox Code Playgroud)
然后在那个区块中,你使用的是那里没有创建的MOC ......
Entry *entry = (Entry *)[customStore.context objectWithID:objectID];
Run Code Online (Sandbox Code Playgroud)
如果您想使用MOC,您必须遵守规则.我将总结规则#1,因为它有几个条款.
如果您使用MOC创建NSConfinementConcurrencyType,则无法调用performBlock该上下文.您必须仅在创建它的线程中使用它.
如果使用NSMainQueueConcurrencyType,则必须从主线程中或通过访问MOC [moc performBlock].
如果使用NSPrivateQueueConcurrencyType,则必须仅使用它[moc performBlock].
编辑
您的商品不同步.您应该只依靠数据实际告诉您的内容.显然,您依靠self.cellInfo.numberOfMediaItems的计数,但它与您的实际数据不同步.
从多个线程更新数据时必须非常小心.您的代码已经"失去了"实际发生的事情.可能是因为您尚未将内容保存到您从中提取数据的上下文中.
阅读Core Data上的文档并发.确保在没有通知所有其他上下文的情况下,您没有在另一个线程中更改任何内容.您应该使用父/子上下文和/或处理DidSave通知来保持数据同步.
| 归档时间: |
|
| 查看次数: |
680 次 |
| 最近记录: |