(在2011-10-11 20:45 +02:00问题末尾添加了另一个更新)
我的应用程序(iPhone)出现了一个奇怪的问题。它有点随机崩溃(见下面的stacktrace)。
app结构是一个UITabBarController,里面有几个UINavigationController。其中一个UINavigationControllers包含一个UITableView,它附有一个NSFetchedResultsController。
我正在从后台线程更新Core Data上下文(使用另一个上下文,然后将其合并到主上下文中)。
我正在为网络使用ASIHTTPRequest,为JSON部分使用TouchJSON(CJSONDeserializer)。
我还使用SafeFetchedResultsController作为UITableView,我的NSFetchedResultsControllerDelegate和SafeFetchedResultsControllerDelegate方法被进一步粘贴。
我不确定导致崩溃的原因。我无法使用模拟器或在Xcode内的设备上启动和运行应用程序来重现它,但我已经能够在未连接到调试器的设备上重现它。
当应用程序从后台恢复时应用程序崩溃的那些时候,后台线程更新了Core Data上下文,我将tab切换到UITableView - 在应用程序崩溃之前,它已经空了半秒左右。
这是stracktrace(来自使用Bugsense.com):
CoreFoundation 0x314d0987 __exceptionPreprocess 114
libobjc.A.dylib 0x319a149d objc_exception_throw 24
CoreFoundation 0x3147c0c1 -[__NSArrayM removeObjectAtIndex:] 300
CoreData 0x352f6051 -[NSFetchedResultsController(PrivateMethods) _postprocessDeletedObjects:] 528
CoreData 0x352f7efb -[NSFetchedResultsController(PrivateMethods) _postprocessUpdatedObjects:] 234
CoreData 0x352fa2d7 -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] 1238
Foundation 0x31cd8623 _nsnote_callback 142
CoreFoundation 0x31457123 __CFXNotificationPost_old 402
CoreFoundation 0x31456dc3 _CFXNotificationPostNotification 118
Foundation 0x31cc7d23 -[NSNotificationCenter postNotificationName:object:userInfo:] 70
CoreData 0x35256e3f -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] 54
CoreData 0x352b3569 -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] 140
CoreData 0x3523f391 -[NSManagedObjectContext(_NSInternalChangeProcessing) _postRefreshedObjectsNotificationAndClearList] 76
CoreData 0x3523f0bf -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] 1814
CoreData 0x35274b15 -[NSManagedObjectContext processPendingChanges] 16
CoreData 0x352677a3 _performRunLoopAction 126
CoreFoundation 0x31460c59 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 16
CoreFoundation 0x31460acd __CFRunLoopDoObservers 412
CoreFoundation 0x314580cb __CFRunLoopRun 854
CoreFoundation 0x31457c87 CFRunLoopRunSpecific 230
CoreFoundation 0x31457b8f CFRunLoopRunInMode 58
GraphicsServices 0x35d664ab GSEventRunModal 114
GraphicsServices 0x35d66557 GSEventRun 62
UIKit 0x338d5329 -[UIApplication _run] 412
UIKit 0x338d2e93 UIApplicationMain 670
MyApp 0x00002a75 0x0 10869
MyApp 0x00002a40 0x0 10816
这是来自iPhone本身崩溃日志的堆栈跟踪:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x3076dd50 __semwait_signal_nocancel + 24
1 libsystem_c.dylib 0x35cc01d8 nanosleep$NOCANCEL + 112
2 libsystem_c.dylib 0x35c82c6c usleep$NOCANCEL + 36
3 libsystem_c.dylib 0x35c82c12 abort + 98
4 libstdc++.6.dylib 0x33f5fe48 __cxxabiv1::__terminate(void (*)()) + 64
5 libstdc++.6.dylib 0x33f5fe8a std::terminate() + 10
6 libstdc++.6.dylib 0x33f5ff5a __cxa_throw + 78
7 libobjc.A.dylib 0x360f3c84 objc_exception_throw + 64
8 CoreFoundation 0x31e1b206 -[__NSArrayM removeObjectAtIndex:] + 294
9 CoreData 0x31a013c6 -[NSFetchedResultsController(PrivateMethods) _postprocessDeletedObjects:] + 522
10 CoreData 0x31a01db8 -[NSFetchedResultsController(PrivateMethods) _postprocessUpdatedObjects:] + 228
11 CoreData 0x31a039c0 -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 1232
12 Foundation 0x31a8617c _nsnote_callback + 136
13 CoreFoundation 0x31e7f208 __CFXNotificationPost_old + 396
14 CoreFoundation 0x31e19ee4 _CFXNotificationPostNotification + 112
15 Foundation 0x31a835cc -[NSNotificationCenter postNotificationName:object:userInfo:] + 64
16 CoreData 0x319a5c00 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 48
17 CoreData 0x319a5fc6 -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] + 134
18 CoreData 0x3196624a -[NSManagedObjectContext(_NSInternalChangeProcessing) _postRefreshedObjectsNotificationAndClearList] + 70
19 CoreData 0x31965f78 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1808
20 CoreData 0x319a739e -[NSManagedObjectContext processPendingChanges] + 10
21 CoreData 0x31941278 _performRunLoopAction + 120
22 CoreFoundation 0x31e87a2e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 10
23 CoreFoundation 0x31e8945e __CFRunLoopDoObservers + 406
24 CoreFoundation 0x31e8a754 __CFRunLoopRun + 848
25 CoreFoundation 0x31e1aebc CFRunLoopRunSpecific + 224
26 CoreFoundation 0x31e1adc4 CFRunLoopRunInMode + 52
27 GraphicsServices 0x300c2418 GSEventRunModal + 108
28 GraphicsServices 0x300c24c4 GSEventRun + 56
29 UIKit 0x35090d62 -[UIApplication _run] + 398
30 UIKit 0x3508e800 UIApplicationMain + 664
31 MyApp 0x000022d2 main (main.m:13)
32 MyApp 0x00002290 start + 32
Thread 1 name: Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0 libsystem_kernel.dylib 0x3076efbc kevent + 24
1 libdispatch.dylib 0x31a6b094 _dispatch_mgr_invoke + 672
2 libdispatch.dylib 0x31a6c04a _dispatch_queue_invoke + 86
3 libdispatch.dylib 0x31a6b60a _dispatch_worker_thread2 + 190
4 libsystem_c.dylib 0x35c8b58a _pthread_wqthread + 258
5 libsystem_c.dylib 0x35c8bbbc start_wqthread + 0
Thread 2 name: WebThread
Thread 2:
0 libsystem_kernel.dylib 0x3076bc00 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x3076b758 mach_msg + 44
2 CoreFoundation 0x31e882b8 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x31e8a562 __CFRunLoopRun + 350
4 CoreFoundation 0x31e1aebc CFRunLoopRunSpecific + 224
5 CoreFoundation 0x31e1adc4 CFRunLoopRunInMode + 52
6 WebCore 0x30b7137a RunWebThread(void*) + 378
7 libsystem_c.dylib 0x35c8a30a _pthread_start + 242
8 libsystem_c.dylib 0x35c8bbb4 thread_start + 0
Thread 3:
0 libsystem_kernel.dylib 0x3076bc00 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x3076b758 mach_msg + 44
2 CoreFoundation 0x31e882b8 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x31e8a562 __CFRunLoopRun + 350
4 CoreFoundation 0x31e1aebc CFRunLoopRunSpecific + 224
5 CoreFoundation 0x31e5d6d2 CFRunLoopRun + 42
6 MyApp 0x0002b4fc +[ASIHTTPRequest runRequests] (ASIHTTPRequest.m:4290)
7 Foundation 0x31a95382 -[NSThread main] + 38
8 Foundation 0x31b075c6 __NSThread__main__ + 966
9 libsystem_c.dylib 0x35c8a30a _pthread_start + 242
10 libsystem_c.dylib 0x35c8bbb4 thread_start + 0
Thread 4:
0 libsystem_kernel.dylib 0x3076bc00 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x3076b758 mach_msg + 44
2 CoreFoundation 0x31e882b8 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x31e8a562 __CFRunLoopRun + 350
4 CoreFoundation 0x31e1aebc CFRunLoopRunSpecific + 224
5 CoreFoundation 0x31e1adc4 CFRunLoopRunInMode + 52
6 Foundation 0x31aa27f6 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 206
7 Foundation 0x31a95382 -[NSThread main] + 38
8 Foundation 0x31b075c6 __NSThread__main__ + 966
9 libsystem_c.dylib 0x35c8a30a _pthread_start + 242
10 libsystem_c.dylib 0x35c8bbb4 thread_start + 0
Thread 5 name: com.apple.CFSocket.private
Thread 5:
0 libsystem_kernel.dylib 0x3076dc60 __select + 20
1 CoreFoundation 0x31e8d8f2 __CFSocketManager + 582
2 libsystem_c.dylib 0x35c8a30a _pthread_start + 242
3 libsystem_c.dylib 0x35c8bbb4 thread_start + 0
Thread 6 Crashed:
0 libsystem_kernel.dylib 0x3076e3ec __workq_kernreturn + 8
1 libsystem_c.dylib 0x35c8b6d8 _pthread_wqthread + 592
2 libsystem_c.dylib 0x35c8bbbc start_wqthread + 0
Thread 7:
0 libsystem_kernel.dylib 0x3076e3ec __workq_kernreturn + 8
1 libsystem_c.dylib 0x35c8b6d8 _pthread_wqthread + 592
2 libsystem_c.dylib 0x35c8bbbc start_wqthread + 0
Thread 8:
0 libsystem_kernel.dylib 0x3076e3ec __workq_kernreturn + 8
1 libsystem_c.dylib 0x35c8b6d8 _pthread_wqthread + 592
2 libsystem_c.dylib 0x35c8bbbc start_wqthread + 0
Thread 6 crashed with ARM Thread State:
r0: 0x00000004 r1: 0x00000000 r2: 0x00000000 r3: 0x00000000
r4: 0x063da000 r5: 0x001701a4 r6: 0x063da000 r7: 0x063d9fe0
r8: 0x00bda680 r9: 0x003fc0a0 r10: 0x3fb033f4 r11: 0x00000000
ip: 0x00000170 sp: 0x063d9fc4 lr: 0x369536df pc: 0x314363ec
cpsr: 0x00000010
#pragma mark -
#pragma mark fetchedResultsController
- (SafeFetchedResultsController*)fetchedResultsController {
if(_fetchedResultsController !=nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext* theContext = [self context];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:theContext];
[fetchRequest setEntity:entity];
//Only events newer than 14 days
NSDate* breakDate = [NSDate dateWithTimeIntervalSinceNow:(-1)*(14*24*60*60)];
NSPredicate *p = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"startDate"]
rightExpression:[NSExpression expressionForConstantValue:breakDate]
modifier:NSDirectPredicateModifier
type:NSGreaterThanPredicateOperatorType
options:0];
[fetchRequest setPredicate:p];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"startDateAsString" ascending:NO];
NSSortDescriptor *sort2= [[NSSortDescriptor alloc] initWithKey:@"eventID" ascending:NO];
NSSortDescriptor *sort3= [[NSSortDescriptor alloc] initWithKey:@"startDate" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sort,sort2,sort3,nil]];
[fetchRequest setFetchBatchSize:12];
SafeFetchedResultsController *theFetchedResultsController = [[SafeFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.context
sectionNameKeyPath:@"startDateAsString"
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
[_fetchedResultsController setSafeDelegate:self];
[_fetchedResultsController setDelegate:self];
[sort release];
[sort2 release];
[sort3 release];
[fetchRequest release];
[theFetchedResultsController release];
return _fetchedResultsController;
}
- (void)controllerDidMakeUnsafeChanges:(NSFetchedResultsController *)controller
{
NSLog(@"Unsafe changes");
[self.tableView reloadData];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if(controller == _fetchedResultsController) {
[self.tableView beginUpdates];
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type {
if(controller == _fetchedResultsController) {
switch(type) {
case NSFetchedResultsChangeInsert:
//if (!((sectionIndex == 0) && ([[self eventTable] numberOfSections] == 1)))
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
// [[self eventTable] insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
// withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeDelete:
//if (!((sectionIndex == 0) && ([[self eventTable] numberOfSections] == 1) ))
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
// [[self eventTable] deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
// withRowAnimation:UITableViewRowAnimationNone];
break;
}
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
if(controller == _fetchedResultsController) {
UITableView* tv = self.tableView;
switch(type)
{
case NSFetchedResultsChangeInsert:
{
//NSLog(@"Insert: %@", StringFromIndexPath(newIndexPath));
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
// [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
// withRowAnimation:UITableViewRowAnimationNone];
break;
}
case NSFetchedResultsChangeDelete:
{
//NSLog(@"Delete: %@", StringFromIndexPath(indexPath));
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
// [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
// withRowAnimation:UITableViewRowAnimationNone];
break;
}
case NSFetchedResultsChangeUpdate:
{
if (newIndexPath == nil)
{
//NSLog(@"Update: %@", StringFromIndexPath(indexPath));
[tv reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
}
else
{
//NSLog(@"Update: %@ -> %@", StringFromIndexPath(indexPath), StringFromIndexPath(newIndexPath));
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
}
break;
}
case NSFetchedResultsChangeMove:
{
//NSLog(@"Move: %@ -> %@", StringFromIndexPath(indexPath), StringFromIndexPath(newIndexPath));
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if(controller == _fetchedResultsController) {
[self.tableView endUpdates];
//[self addNoEntriesFooterToTableViewIfNecessary:self.eventTable];
}
[self addNoEntriesFooterToTableViewIfNecessary:self.tableView];
}
主要问题是我目前不知道从哪里开始寻找错误,因为我无法弄清楚它的起源。希望有人可以解决这个问题。
只需添加评论哪些信息有用,我就会更新问题。
提前致谢!
这可能与它有关吗? 就像那样,核心数据正忙于在视图出现的那一刻处理更新。如果是这样,处理这样的问题的正确方法是什么?
//myTableViewController.m
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSError *error2;
if(![self.fetchedResultsController performFetch:&error2]) {
NSLog(@"Unresolved error %@ %@",error2,[error2 userInfo]);
exit(-1);
}
}
我认为我能够在控制台运行的情况下重新创建崩溃(但不是通过Xcode启动的应用程序)。
这是控制台揭示的内容:
Oct 11 20:40:41 unknown myApp[754] <Warning>: Received memory warning. Level=2
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-06' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-06' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-08' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-11' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-06' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-11' not found in controller
Oct 11 20:40:42 unknown myApp[754] <Warning>: NSFetchedResultsController error: section '2011-10-11' not found in controller
我不认为它实际上是我的应用程序导致内存警告,但我知道 - 它仍然必须能够处理它。
这就是didRecieveMemoryWarning的样子:
//myTableViewController.m
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
if([[self.navigationController viewControllers] count]>1) {
} else {
[super didReceiveMemoryWarning];
}
[detailController release];
detailController = nil;
// Relinquish ownership any cached data, images, etc. that aren't in use.
[NSFetchedResultsController deleteCacheWithName:[_fetchedResultsController cacheName]];
}
我认为[[self.navigationController viewControllers] count]>1
条件的目的是检查视图是否没有呈现子视图(因为它在UINavigationController中),但是我不确定这个条件是否应该在这里或不。这真的可能是事故的原因吗?
在这种情况下,还有更好的方法来处理内存警告吗?