ALAssetsLibrary error - "Too many contexts. No space in contextList." - ios

I've received a couple of crash reports from users. I don't even know where to begin on this one. I am showing images from the asset library in a table view starting with a list of groups. I load the groups with the following code (on the main thread):
- (ALAssetsLibrary *)library {
if (!_library) {
_library = [[ALAssetsLibrary alloc] init];
}
return _library;
}
- (void)determineGroups {
ALAssetsLibrary *lib = [self library];
[lib enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos | ALAssetsGroupPhotoStream | ALAssetsGroupFaces | ALAssetsGroupLibrary | ALAssetsGroupAlbum | ALAssetsGroupEvent usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
if (!_groups) {
_groups = [[NSMutableArray alloc] init];
}
if ([group numberOfAssets]) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
if ([[group valueForProperty:ALAssetsGroupPropertyType] isEqual:#(ALAssetsGroupSavedPhotos)]) {
[_groups insertObject:group atIndex:0];
} else {
[_groups addObject:group];
}
}
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
} failureBlock:^(NSError *error) {
// denied
dispatch_async(dispatch_get_main_queue(), ^{
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.tableView reloadData];
});
}];
}
When populating the table view I want to show the number of photos in each group. I do this by calling the "numberOfAssets" method on the group.
This all works just fine most of the time but crashes on rare occasions. Here is one of the stack traces with the relevant info (thread 5 crashed while the main thread was busy getting the number of assets in the group):
Crashed Thread: 5
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Too many contexts. No space in contextList.'
Thread 0:
0 CoreFoundation 0x313a1c42 _CFStringGetLength2 + 26
1 CoreFoundation 0x313aba41 -[__NSDictionaryM objectForKey:] + 133
2 CoreData 0x312b5d2f -[NSSQLOrderIntermediate generateSQLStringInContext:] + 1283
3 CoreData 0x312018f7 -[NSSQLFetchIntermediate generateSQLStringInContext:] + 515
4 CoreData 0x311fe625 -[NSSQLGenerator newSQLStatementForFetchRequest:ignoreInheritance:countOnly:nestingLevel:] + 425
5 CoreData 0x311fe3ad -[NSSQLAdapter _newSelectStatementWithFetchRequest:ignoreInheritance:] + 509
6 CoreData 0x311fdfc5 -[NSSQLCore newRowsForFetchPlan:] + 117
7 CoreData 0x311fd73f -[NSSQLCore objectsForFetchRequest:inContext:] + 683
8 CoreData 0x311fd205 -[NSSQLCore executeRequest:withContext:error:] + 469
9 CoreData 0x311fc61d -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1645
10 CoreData 0x311faf17 -[NSManagedObjectContext executeFetchRequest:error:] + 647
11 PhotoLibraryServices 0x366cd4e5 -[PLManagedObjectContext executeFetchRequest:error:] + 49
12 CoreData 0x3121ad07 _faultBatchAtIndex + 623
13 CoreData 0x3121aa53 -[_PFBatchFaultingArray getObjects:range:] + 143
14 CoreData 0x3121a9c1 -[_PFBatchFaultingArray getObjects:] + 41
15 Foundation 0x31cfbbe1 _filterObjectsUsingPredicate + 325
16 Foundation 0x31d01b8d -[NSArray(NSPredicateSupport) filteredArrayUsingPredicate:] + 273
17 PhotoLibraryServices 0x366d86ad +[PLFilteredAlbum filteredIndexesInAlbum:predicate:] + 265
18 PhotoLibraryServices 0x366d8bd1 -[PLFilteredAlbum filteredIndexes] + 117
19 PhotoLibraryServices 0x366d8d75 -[PLFilteredAlbum countOfFilteredAssets] + 21
20 AssetsLibrary 0x30ce25d5 __31-[ALAssetsGroup numberOfAssets]_block_invoke_0 + 41
21 CoreData 0x31257fd1 developerSubmittedBlockToNSManagedObjectContextPerform + 89
22 libdispatch.dylib 0x3971d4b7 _dispatch_client_callout + 23
23 libdispatch.dylib 0x397219f7 _dispatch_barrier_sync_f_invoke + 31
24 CoreData 0x31258153 -[NSManagedObjectContext performBlockAndWait:] + 175
25 AssetsLibrary 0x30ce414f -[ALAssetsLibrary _performBlockAndWait:] + 135
26 AssetsLibrary 0x30ce8f59 -[ALAssetsGroupPrivate _performBlockAndWait:] + 177
27 AssetsLibrary 0x30ce254b -[ALAssetsGroup numberOfAssets] + 259
Thread 5 Crashed:
0 libsystem_kernel.dylib 0x39804350 __pthread_kill + 8
1 libsystem_c.dylib 0x397b7973 abort + 95
2 MyApp 0x0074685f ___lldb_unnamed_function30167$$MyApp + 27
3 CoreFoundation 0x3145b57f __handleUncaughtException + 615
4 libobjc.A.dylib 0x39306a65 _objc_terminate() + 129
5 libc++abi.dylib 0x38d5307b safe_handler_caller(void (*)()) + 79
6 libc++abi.dylib 0x38d53114 std::terminate() + 20
7 libc++abi.dylib 0x38d54513 __cxa_throw + 123
8 libobjc.A.dylib 0x393069bf objc_exception_throw + 95
9 CoreFoundation 0x3145b15d +[NSException raise:format:] + 1
10 Foundation 0x31d30b13 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 87
11 PhotoLibraryServices 0x366d0afb __addContextToList_block_invoke_0 + 179
12 libdispatch.dylib 0x3971e11f _dispatch_call_block_and_release + 11
13 libdispatch.dylib 0x39721ecf _dispatch_queue_drain$VARIANT$mp + 143
14 libdispatch.dylib 0x39721dc1 _dispatch_queue_invoke$VARIANT$mp + 41
15 libdispatch.dylib 0x3972291d _dispatch_root_queue_drain + 185
16 libdispatch.dylib 0x39722ac1 _dispatch_worker_thread2 + 85
17 libsystem_c.dylib 0x39752a11 _pthread_wqthread + 361
The crash was from an iPad running iOS 6.1.3. The app was built with a Base SDK of iOS 7 GM. The app uses ARC.
Is there something i should be doing different in my code to get the groups?

Definitely it is iOS issue and is reproduced when enumerateGroupsWithTypes:... method contains ALAssetsGroupLibrary inside types enumeration.
You must use either ALAssetsGroupALL (that does not include ALAssetsGroupLibrary)
or you may enumerate types with OR but don't include ALAssetsGroupLibrary to enumeration.
I don't know what to do if you really need ALAssetGroupLibrary in types enumeration.
My code is very similar to yours; if you want to reproduce this issue try to call determineGroups method many times (my issue reproduces when I do this 11 times exactly) but library object must be recreated each time you call this method (f.e. You may remove library at the end of determineGroups method.
Or you may call determineGroups method each time for new receiver.). Also to reproduce this issue don't call determineGroups method inside single run loop
it would be better if you create button and tap on this button would create new receiver and calls determineGroups for it. Now try to tap on this button many times.
Hope my answer will help you.

I fix this by creating a sigleton object when using the ALAssetsLibrary.
+ (instancetype)defaultAssetsLibrary
{
#synchronized(self) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defaultAssetsLibrary = [[self alloc] init];
});
}
return defaultAssetsLibrary;
}

Related

CoreData _NSIsNSSet EXC_BAD_ACCESS KERN_INVALID_ADDRESS - crash on app launch

We are getting this crash on multiple devices but cannot figure out where it originates from. The main thread is crashing.
Stack trace:
Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x193dfd58c object_getMethodImplementation + 20
1 CoreFoundation 0x1940f6928 _NSIsNSSet + 40
2 CoreFoundation 0x193fc2c04 -[NSMutableSet unionSet:] + 112
3 CoreData 0x198abe014 -[_NSFaultingMutableSet willReadWithContents:] + 668
4 CoreData 0x198ae4280 -[_NSFaultingMutableSet count] + 32
5 CoreData 0x198be1bb4 __107-[NSManagedObjectContext(_NestedContextSupport) newValueForRelationship:forObjectWithID:withContext:error:]_block_invoke + 360
6 CoreData 0x198be2e70 internalBlockToNSManagedObjectContextPerform + 104
7 libdispatch.dylib 0x193d8b5ac _dispatch_client_callout + 20
8 libdispatch.dylib 0x193d9843c _dispatch_async_and_wait_invoke + 96
9 libdispatch.dylib 0x193d8b5ac _dispatch_client_callout + 20
10 libdispatch.dylib 0x193d977d4 _dispatch_main_queue_callback_4CF + 832
11 CoreFoundation 0x1940648d4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
12 CoreFoundation 0x19405f58c __CFRunLoopRun + 1692
13 CoreFoundation 0x19405ebc8 CFRunLoopRunSpecific + 480
14 GraphicsServices 0x19e4475cc GSEventRunModal + 164
15 UIKitCore 0x198211744 UIApplicationMain + 1936
16 My App 0x100b37324 main + 16 (main.m:16)
17 libdyld.dylib 0x193edb384 start + 4
At the same time, a background thread operating in a PrivateQueue ManagedObjectContext is busy accessing a ManagedObject via awakeFromFetch, stack trace of this thread:
NSManagedObjectContext 0x28066c700
0 libsystem_kernel.dylib 0x1b09617e4 __ulock_wait + 8
1 libdispatch.dylib 0x1b081bf48 _dlock_wait + 56
2 libdispatch.dylib 0x1b081bcf4 _dispatch_thread_event_wait_slow + 56
3 libdispatch.dylib 0x1b0828618 __DISPATCH_WAIT_FOR_QUEUE__ + 336
4 libdispatch.dylib 0x1b0828204 _dispatch_sync_f_slow + 144
5 CoreData 0x1b56686cc _perform + 200
6 CoreData 0x1b558e2c4 -[NSManagedObjectContext(_NestedContextSupport) newValueForRelationship:forObjectWithID:withContext:error:] + 156
7 CoreData 0x1b555033c -[NSFaultHandler retainedFulfillAggregateFaultForObject:andRelationship:withContext:] + 428
8 CoreData 0x1b554df10 -[_NSFaultingMutableSet willReadWithContents:] + 408
9 CoreData 0x1b55ea5bc -[_NSFaultingMutableSet allObjects] + 32
10 My App 0x1044fdc3c PSUser.isAdmin.getter + 286 (PSUser.swift:286)
11 My App 0x1044fdb04 #objc PSUser.isAdmin.getter + 4309900036 (<compiler-generated>:4309900036)
12 My App 0x1044fc694 PSUser.initCurrentTeam() + 212 (PSUser.swift:212)
13 My App 0x1044fcbc0 #objc PSUser.initCurrentTeam() + 4309896128 (<compiler-generated>:4309896128)
14 My App 0x1044fc658 #objc PSUser.awakeFromFetch() + 4309894744 (<compiler-generated>:4309894744)
15 CoreData 0x1b56520e4 _PFFaultHandlerFulfillFault + 3168
16 CoreData 0x1b5650ab0 _PFFaultHandlerLookupRow + 908
17 CoreData 0x1b56527fc _PF_FulfillDeferredFault + 260
18 CoreData 0x1b5666a2c _pvfk_header + 120
19 CoreData 0x1b5663218 _sharedIMPL_pvfk_core + 32
20 My App 0x10438918c +[PSAppSettings isAutoPilotAllowed:] + 97 (PSAppSettings.m:97)
21 My App 0x1043fbb9c LocationTracker.updateTrackingState(user:) + 1120 (LocationTracker.swift:1120)
22 My App 0x104413b4c partial apply for closure #1 in LocationTracker.store(filteredLocations:) + 1275 (LocationTracker.swift:1275)
23 My App 0x1043bae3c thunk for #escaping #callee_guaranteed () -> () + 4308577852 (<compiler-generated>:4308577852)
24 CoreData 0x1b566b650 developerSubmittedBlockToNSManagedObjectContextPerform + 164
25 libdispatch.dylib 0x1b081b5ac _dispatch_client_callout + 20
26 libdispatch.dylib 0x1b0821a64 _dispatch_lane_serial_drain + 568
27 libdispatch.dylib 0x1b0822498 _dispatch_lane_invoke + 400
28 libdispatch.dylib 0x1b082ba5c _dispatch_workloop_worker_thread + 584
29 libsystem_pthread.dylib 0x1b0881718 _pthread_wqthread + 276
30 libsystem_pthread.dylib 0x1b08879c8 start_wqthread + 8
I am not certain if the two stacks are related, or if the background thread is dispatching anything to the main thread (why should it?), but the call newValueForRelationship:forObjectWithID:withContext:error does appear in both stack traces.
The method for awakeFromFetch is initializing a calculated object property currentTeam via the initCurrentTeam() method. This method accesses the teams relationship on that object. Here is the relevant code:
#objc extension PSUser {
override open func awakeFromFetch() {
super.awakeFromFetch()
initCurrentTeam()
}
/**
This method sets the currentTeam by picking
the appropriate team from the `teams` set.
*/
func initCurrentTeam() {
if (isAdmin || isManager), !isEmployee,
var teams = teams?.allObjects as? [PSTeam],
currentTeam == nil {
...
currentTeam = teams.first
}
}
...
}
Enabled com.apple.CoreData.ConcurrencyDebug in Xcode Scheme but Xcode console does not complain. I have not been able to reproduce this issue while debugging in Xcode. The issue is only reported via Crashlytics in production environment.
Any ideas what might be causing this?

SIGSEGV : Sporadic crash issue

Here is my first attempt to solve crash issue in iOS app. Sharing some crash logs here.
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x97ad6beb8
Crashed Thread: 11
Application Specific Information:
objc_msgSend() selector name: length
and here is my 11th thread.
Thread 11 Crashed:
0 libobjc.A.dylib 0x0000000180558150 objc_msgSend + 16
1 Foundation 0x00000001824f3f60 -[NSString compare:] + 28
2 Foundation 0x00000001824d88e0 _NSCompareObject + 60
3 CoreFoundation 0x0000000181a99bd0 __CFSimpleMergeSort + 88
4 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
5 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
6 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
7 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
8 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
9 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
10 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
11 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
12 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
13 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
14 CoreFoundation 0x0000000181a99c60 __CFSimpleMergeSort + 232
15 CoreFoundation 0x00000001819c585c CFSortIndexes + 460
16 CoreFoundation 0x00000001819c6f9c CFMergeSortArray + 372
17 Foundation 0x00000001824d80e8 _sortedObjectsUsingDescriptors + 568
18 Foundation 0x00000001825c64e0 -[NSSet(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 536
19 Eikon 0x0000000100198b98 __51-[EIKNewsHeadlineStoreManager saveHeadlines:block:]_block_invoke (EIKNewsHeadlineStoreManager.m:67)
20 CoreData 0x0000000183e5e214 developerSubmittedBlockToNSManagedObjectContextPerform + 148
21 libdispatch.dylib 0x000000018099a9a0 _dispatch_client_callout + 12
22 libdispatch.dylib 0x00000001809a8ad4 _dispatch_queue_serial_drain + 924
23 libdispatch.dylib 0x000000018099e2cc _dispatch_queue_invoke + 880
24 libdispatch.dylib 0x00000001809a8fa8 _dispatch_queue_override_invoke + 340
25 libdispatch.dylib 0x00000001809aaa50 _dispatch_root_queue_drain + 536
26 libdispatch.dylib 0x00000001809aa7d0 _dispatch_worker_thread3 + 120
27 libsystem_pthread.dylib 0x0000000180ba31d0 _pthread_wqthread + 1092
28 libsystem_pthread.dylib 0x0000000180ba2d7c start_wqthread + 0
What i am trying to do is get some news headlines from server every 5 or 10 secs, sort them in some order using NSSortDescriptors and then store them in my CoreData. And that is what exactly saveHeadlines:block method is doing inside my class.
What exactly objc_msgSend() selector name: length
mean here? Any help is appreciated.
Note: Its a sporadic issue. When i test in simulator or my devices its not crashing. But some users of our app are reporting this crash.
Edited question: inside saveHeadlines:block method
__weak typeof(self) weakSelf = self;
[self.privateMOC performBlock:^{
NSMutableArray *newsTopics = [[EIKNewsTopicStoreManager managedObjectsInManagedObjectContext:self.privateMOC] mutableCopy];
[newsTopics addObjectsFromArray:[EIKNewsTopicStoreManager topicsManagedObjectForNewsFeedInContext:self.privateMOC]];
weakSelf.storedHeadlines = [NSMutableSet set];
for (NSManagedObject *storedTopic in newsTopics) {
[weakSelf.storedHeadlines addObjectsFromArray:[[storedTopic valueForKey:EIKFeedTopicRelationshipItems] allObjects]];
}
NSArray *sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:EIKNewsHeadlineAttributeHeadlineId ascending:YES]];
NSArray *orderedItems = [items sortedArrayUsingDescriptors:sortDescriptors];
NSArray *orderedHeadlines = [weakSelf.storedHeadlines sortedArrayUsingDescriptors:sortDescriptors];
And the crash is happening on the last line. i.e
NSArray *orderedHeadlines = [weakSelf.storedHeadlines sortedArrayUsingDescriptors:sortDescriptors];
Not able to figure out why.!
My NSManagedObjectContext is initialised like this[i.e privateMOC as shown in above code]
NSManagedObjectContext *confinementContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
Not much info here, but it looks to me that NSManagedObjectContext isn't valid on the thread you are performing your operation.
Please make sure that you perform all operations on the context's private queue. You can do this for example by using performBlock: or performBlockAndWait:.
Also you can't reuse instances of NSManagedObject on different threads than the one you fetched them on.
Hope that helps.

iOS Crash SIGABRT happens sometimes

I've got an app in the Appstore which sometimes crashes. I havent been able to reproduce the bug.
The crash I get in Fabric.
Thread : Crashed: com.apple.root.default-qos
0 libsystem_kernel.dylib 0x0000000197b1b270 __pthread_kill + 8
1 libsystem_pthread.dylib 0x0000000197bb9228 pthread_kill + 112
2 libsystem_c.dylib 0x0000000197a92b18 abort + 112
3 libsystem_malloc.dylib 0x0000000197b563e4 _nano_malloc_check_clear
4 libsystem_malloc.dylib 0x0000000197b56550 _nano_malloc_check_clear + 364
5 libsystem_malloc.dylib 0x0000000197b55064 nano_malloc + 44
6 libsystem_malloc.dylib 0x0000000197b453e4 malloc_zone_malloc + 116
7 CoreFoundation 0x0000000186cb179c __CFBasicHashRehash + 264
8 CoreFoundation 0x0000000186cb2f8c __CFBasicHashAddValue + 100
9 CoreFoundation 0x0000000186b60454 CFDictionarySetValue + 252
10 ImageIO 0x0000000187e3fab0 initImagePng + 2800
11 ImageIO 0x0000000187e3e804 makeImagePlus + 1056
12 ImageIO 0x0000000187e3df30 CGImageSourceCreateImageAtIndex + 184
13 UIKit 0x000000018b57cd94 _UIImageRefFromData + 296
14 UIKit 0x000000018b6e156c -[UIImage(UIImagePrivate) _initWithData:preserveScale:cache:] + 112
15 UIKit 0x000000018b57cc3c +[UIImage imageWithData:] + 60
16 APP 0x000000010007b4f4 __28+[XTTeamLogo logo:callback:]_block_invoke (XTTeamLogo.m:94)
17 libdispatch.dylib 0x00000001979d93ac _dispatch_call_block_and_release + 24
18 libdispatch.dylib 0x00000001979d936c _dispatch_client_callout + 16
19 libdispatch.dylib 0x00000001979e540c _dispatch_root_queue_drain + 1152
20 libdispatch.dylib 0x00000001979e675c _dispatch_worker_thread3 + 108
21 libsystem_pthread.dylib 0x0000000197bb52e4 _pthread_wqthread + 816
So number 16 is one of my code which gives me a hint to check line number 94 in XTTeamLogo. Which contains this code:
__block XTTeamLogo *logo;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^(void) {
...SERVER REQUEST...
if (!localizedError) {
NSData *binary = [[[result getMessageByPath:#"DocumentData"] getPropertyByPath:#"Data"] binary];
if (binary) {
->(94) logo = [[XTTeamLogo alloc] initWithImage:[UIImage imageWithData:binary] fromCache:NO];
[[XTDisk sharedInstance] write:logo fileName:kPersistents];
[[XTCache sharedInstance] setObject:logo forKey:kPersistents];
}
}
... ERROR HANDLING ETC...
dispatch_async(dispatch_get_main_queue(), ^(void){
callback(logo, localizedError);
});
});
I assume from your comment "It is serverside resized..." that binary was loaded from the server.
What happens if your variable binary is not really your binary image data, but a String (i.e. which was received from a hotel network login page or other network foobar)?
Just try to check if XTTeamLogo can handle it
NSString* testString = #"dummy test string data. maybe it must be longer";
NSData* binary = [testString dataUsingEncoding:NSUTF8StringEncoding];
If this it is, you should check the mime-type of your network response before assuming that you have received your image data.

CoreData MagicalRecord save methods crashes on iPhone5

Currently I'm working with MagicalRecord v2.3.0-beta.3 commit:d18e74fe435359238b9593c03e41c1ee0baa0b78 framework. I'm getting 1 a crash log (from Crashlytics) on iPhone 5 all the time. App is still in development. The crash log looks like below:
Thread : Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x38eee626 objc_msgSend + 5
1 Foundation 0x2f06d02d -[NSError dealloc] + 60
2 libobjc.A.dylib 0x38ef3b6b objc_object::sidetable_release(bool) + 174
3 libobjc.A.dylib 0x38ef40d3 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358
4 CoreFoundation 0x2e67d481 _CFAutoreleasePoolPop + 16
5 Foundation 0x2f0778e3 -[NSAutoreleasePool drain] + 122
6 CoreData 0x2e4bdfbf -[NSManagedObjectContext save:] + 942
7 MyApp 0x00162f9f __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke15 (NSManagedObjectContext+MagicalSaves.m:82) // here app crashes
8 CoreData 0x2e5219cd developerSubmittedBlockToNSManagedObjectContextPerform + 88
9 CoreData 0x2e521b13 -[NSManagedObjectContext performBlockAndWait:] + 114
10 MyApp 0x00162e51 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:] (NSManagedObjectContext+MagicalSaves.m:116)
11 MyApp 0x000a2b0d -[SPNCoreDataHandler parseAndSaveDictionaryReturnOperationArray:withSaving:] (SPNCoreDataHandler.m:70)
12 MyApp 0x00078f21 __102-[SPNApiHandler getAllDataWithDownloadingSuccessBlock:savingSuccessBlock:downloadStatus:failureBlock:]_block_invoke (SPNApiHandler.m:69)
13 MyApp 0x000795b9 __66-[SPNApiHandler sendGetRequestWithPath:successBlock:failureBlock:]_block_invoke (SPNApiHandler.m:174)
14 libdispatch.dylib 0x393cdd53 _dispatch_call_block_and_release + 10
15 libdispatch.dylib 0x393cdd3f _dispatch_client_callout + 22
16 libdispatch.dylib 0x393d06c3 _dispatch_main_queue_callback_4CF + 278
17 CoreFoundation 0x2e714641 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
18 CoreFoundation 0x2e712f0d __CFRunLoopRun + 1308
19 CoreFoundation 0x2e67d729 CFRunLoopRunSpecific + 524
20 CoreFoundation 0x2e67d50b CFRunLoopRunInMode + 106
21 GraphicsServices 0x335ec6d3 GSEventRunModal + 138
22 UIKit 0x30fde871 UIApplicationMain + 1136
23 MyApp 0x0009c347 main (main.m:16)
And here's code which I wrote:
NOTE: I removed some parts of this method for sake of readability (that's why method returns void instead of NSArray).
- (NSArray *)parseAndSaveDictionaryReturnOperationArray:(NSDictionary *)dictionary withSaving:(BOOL)saveSynchrounously {
[self truncateAll]; //method which removes all entries in coreData
/* methods below creates entities from array given in dictionary
using [NSManagedObject MR_createEntity] method
e.g. Contact *contact = [Contact MR_createEntity]; */
[self saveContacts:dictionary[#"contact"]];
[self savePeople:dictionary[#"person"]];
[self saveBuildings:dictionary[#"place"]];
[self saveSessions:dictionary[#"session"]];
[self saveLectures:dictionary[#"program"]];
[self savePartners:dictionary[#"partners"]];
[self saveSponsors:dictionary[#"sponsors"]];
[self saveExhibitorsPlans:dictionary[#"exhibitorplan"]];
[self saveMeetingPlans:dictionary[#"meetingplan"]];
[self saveOrganizationalInformation:dictionary[#"info"]];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
//continue executing method...
}
I tried also to use [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreWithCompletion:] method but it crashes too.
In other Stackoverflow question someone suggested, that crash can be caused by deleting, creating and saving to many entities at once. In my case it's around 200 deleted entities + 200 new ones. Can it cause crash?
On other devices (iPhone 4s, iPhone 5s, iPad 2, iPad4, iPad mini) it works fine. Any ideas what I'm doing wrong?
Finally I found out what was going on. Tester didn't delete and install an app as I told. Crash appears because DB schema changed. Maybe I should start to think about DB versioning during development to avoid those kind of issues.
Thanks anyone for answers.

Core Data crashing when doing count request using performBlock

My iOS app is crashing when doing two calls to countForFetchRequest at the same time on the same private queue NSManagedObjectContext using performBlock.
I setup my childContext like this
_childContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext setParentContext:self.managedObjectContext];
And this is my performBlock that calls countForFetchRequest
[self.childContext performBlock:^{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"History"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"url == %#", url];
NSError *error = nil;
NSUInteger num = [self.childContext countForFetchRequest:fetchRequest error:&error];
if(error != nil){
NSLog(#"Error getting count for history url %# %#", url, error);
return;
}
if(num > 0){ // Already have this in the history, don't re-add it
return;
}
History *history = (History *)[NSEntityDescription insertNewObjectForEntityForName:#"History" inManagedObjectContext:self.childContext];
history.url = url;
history.title = title;
if(![self.childContext save:&error]){
NSLog(#"Error occurred saving history item %# %# %#", title, url, error);
}
}];
And here is the crash log:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x3a427350 __pthread_kill + 8
1 libsystem_c.dylib 0x3a39e11e pthread_kill + 54
2 libsystem_c.dylib 0x3a3da96e abort + 90
3 libc++abi.dylib 0x39978d4a abort_message + 70
4 libc++abi.dylib 0x39975ff4 default_terminate() + 20
5 libobjc.A.dylib 0x39f29a74 _objc_terminate() + 144
6 libc++abi.dylib 0x39976078 safe_handler_caller(void (*)()) + 76
7 libc++abi.dylib 0x39976110 std::terminate() + 16
8 libc++abi.dylib 0x39977594 __cxa_rethrow + 84
9 libobjc.A.dylib 0x39f299cc objc_exception_rethrow + 8
10 CoreData 0x31e868e0 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] + 764
11 CoreData 0x31e833fe -[NSManagedObjectContext countForFetchRequest:error:] + 1062
12 CoreData 0x31e92470 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0 + 460
13 libdispatch.dylib 0x3a345d26 _dispatch_barrier_sync_f_slow_invoke + 82
14 libdispatch.dylib 0x3a3404b4 _dispatch_client_callout + 20
15 libdispatch.dylib 0x3a3451b8 _dispatch_main_queue_callback_4CF$VARIANT$mp + 220
16 CoreFoundation 0x3205cf36 __CFRunLoopRun + 1286
17 CoreFoundation 0x31fcfeb8 CFRunLoopRunSpecific + 352
18 CoreFoundation 0x31fcfd44 CFRunLoopRunInMode + 100
19 GraphicsServices 0x35b992e6 GSEventRunModal + 70
20 UIKit 0x33ee52fc UIApplicationMain + 1116
21 Accountable2You Mobile 0x000e5d28 0xe4000 + 7464
22 Accountable2You Mobile 0x000e5cc4 0xe4000 + 7364
Thread 1 name: Dispatch queue: NSManagedObjectContext Queue
Thread 1:
0 libsystem_kernel.dylib 0x3a416f04 semaphore_wait_trap + 8
1 libdispatch.dylib 0x3a3462fc _dispatch_thread_semaphore_wait$VARIANT$mp + 8
2 libdispatch.dylib 0x3a34487c _dispatch_barrier_sync_f_slow + 96
3 CoreData 0x31e82df2 _perform + 166
4 CoreData 0x31e921c6 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 238
5 CoreData 0x31e86770 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] + 396
6 CoreData 0x31e833fe -[NSManagedObjectContext countForFetchRequest:error:] + 1062
7 Accountable2You Mobile 0x000ee7be 0xe4000 + 42942
8 CoreData 0x31e86072 developerSubmittedBlockToNSManagedObjectContextPerform_privateasync + 66
9 libdispatch.dylib 0x3a344eca _dispatch_queue_drain$VARIANT$mp + 138
10 libdispatch.dylib 0x3a344dbc _dispatch_queue_invoke$VARIANT$mp + 36
11 libdispatch.dylib 0x3a34591a _dispatch_root_queue_drain + 182
12 libdispatch.dylib 0x3a345abc _dispatch_worker_thread2 + 80
13 libsystem_c.dylib 0x3a375a0e _pthread_wqthread + 358
14 libsystem_c.dylib 0x3a3758a0 start_wqthread + 4
Am I using the performBlock correctly?
Edit: More details
The performBlock is being called in a webViewDidFinishLoad:webView delegate method. I have multiple UIWebViews and when they finish loading they are calling the delegate method which is in turn calling the performBlock to see if it needs to add the url to the core data database.
You can encapsulate the method causing the crash in:
#synchronized(self) {
[object yourMethod];
}
This will make sure that even while multithreading, the piece of code inside will be running just once at a time ... other threads will just have to wait. Frankly, this will work only if the cause of the crash is the concurrency.

Resources