iCloud/CoreData Crashing [NSFetchResultsController _computeSectionInfo:error]

Since iOS 16 code that has been working for many years has been randomly crashing on some devices. We have NEVER seen it on any of our devices, but we are getting a lot of complaints and bad reviews from a small percentage of our installed base but which amounts to A LOT of users.

This appears to be an iOS 16 bug that only manifests if users are allowing us to store data in iCloud. below is a typical crash report. Anyone else seeing this and have any ideas on a workaround.

AND APPLE please get on this issue!

Incident Identifier: 1AB6F163-8B35-4D8E-A78A-9514BFD2410B Beta Identifier: 82FFD7BA-5E70-40B9-B45E-B98F320675DF Hardware Model: iPhone14,5 Process: iPhemeris [9907] Path: /private/var/containers/Bundle/Application/5F6EDD27-0AB7-4AFC-B62C-88D29545C12C/iPhemeris.app/iPhemeris Identifier: cribaudo.iphemeris Version: 11.6.1 (146) AppStoreTools: 14E221 AppVariant: 1:iPhone14,5:16 Beta: YES Code Type: ARM-64 (Native) Role: Foreground Parent Process: launchd [1] Coalition: cribaudo.iphemeris [1985]

Date/Time: 2023-03-22 23:17:38.5970 +0800 Launch Time: 2023-03-22 23:17:37.9265 +0800 OS Version: iPhone OS 16.3.1 (20D67) Release Type: User Baseband Version: 2.40.01 Report Version: 104

Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x00000e387afc8fa0 -> 0x000000387afc8fa0 (possible pointer authentication failure) Exception Codes: 0x0000000000000001, 0x00000e387afc8fa0 VM Region Info: 0x387afc8fa0 is in 0x1000000000-0x7000000000; bytes after start: 173862064032 bytes before end: 238454796383 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL commpage (reserved) fc0000000-1000000000 [ 1.0G] ---/--- SM=NUL ...(unallocated) ---> GPU Carveout (reserved) 1000000000-7000000000 [384.0G] ---/--- SM=NUL ...(unallocated) UNUSED SPACE AT END Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [9907]

Triggered by Thread: 0

Kernel Triage: VM - pmap_enter retried due to resource shortage VM - pmap_enter retried due to resource shortage VM - pmap_enter retried due to resource shortage VM - pmap_enter retried due to resource shortage VM - pmap_enter retried due to resource shortage

Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libobjc.A.dylib 0x1cf9e5c20 objc_msgSend + 32 1 CoreFoundation 0x1d6864908 isEqualToString + 100 2 CoreData 0x1de140760 -[NSFetchedResultsController _computeSectionInfo:error:] + 712 3 CoreData 0x1de0c9c08 __43-[NSFetchedResultsController performFetch:]_block_invoke + 520 4 CoreData 0x1de102df8 developerSubmittedBlockToNSManagedObjectContextPerform + 156 5 CoreData 0x1de102948 -[NSManagedObjectContext performBlockAndWait:] + 208 6 CoreData 0x1de0dfb24 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 152 7 CoreData 0x1de0dda10 -[NSFetchedResultsController performFetch:] + 252 8 iPhemeris 0x104f26df8 -[SavedChartViewController initializeFetchedResultsController] + 460 9 iPhemeris 0x104f24560 -[SavedChartViewController viewDidLoad] + 1960 10 UIKitCore 0x1d8db205c -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 84 11 UIKitCore 0x1d8a4a35c -[UIViewController loadViewIfRequired] + 712 12 UIKitCore 0x1d8d10d68 -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 124 13 UIKitCore 0x1d8bd7470 -[UINavigationController _startTransition:fromViewController:toViewController:] + 196 14 UIKitCore 0x1d8bd6928 -[UINavigationController _startDeferredTransitionIfNeeded:] + 608 15 UIKitCore 0x1d8bd5f78 -[UINavigationController __viewWillLayoutSubviews] + 96 16 UIKitCore 0x1d8bd5edc -[UILayoutContainerView layoutSubviews] + 172 17 UIKitCore 0x1d8a344c8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1980 18 QuartzCore 0x1d7f077fc CA::Layer::layout_if_needed(CA::Transaction*) + 500 19 QuartzCore 0x1d7f1aeb0 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 148 20 QuartzCore 0x1d7f2c234 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 444 21 QuartzCore 0x1d7f61630 CA::Transaction::commit() + 652 22 UIKitCore 0x1d8ec32b0 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 36 23 CoreFoundation 0x1d689e514 CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK + 28 24 CoreFoundation 0x1d6906d6c __CFRunLoopDoBlocks + 368 25 CoreFoundation 0x1d68d6b90 __CFRunLoopRun + 856 26 CoreFoundation 0x1d68dbeb0 CFRunLoopRunSpecific + 612 27 GraphicsServices 0x210ad1368 GSEventRunModal + 164 28 UIKitCore 0x1d8dd1668 -[UIApplication _run] + 888 29 UIKitCore 0x1d8dd12cc UIApplicationMain + 340 30 iPhemeris 0x104f18d1c main + 72 31 dyld 0x1f51d4960 start + 2528

From the crash report you provided, the crash seems to be related to the Core Data framework, specifically when fetching data using NSFetchedResultsController. Since you mentioned that it only happens for users who have iCloud enabled, it might be related to how the data is synchronized between the local store and iCloud.

Here are a few suggestions to help you investigate and potentially fix the issue:

Make sure your Core Data stack is set up correctly to handle iCloud integration. Review your NSPersistentStoreCoordinator setup to ensure it has the necessary iCloud options.

Check if there are any issues with the data model, such as missing or incorrect relationships, which might be causing issues when fetching data from the store.

If possible, attempt to reproduce the issue using a device or simulator running iOS 16 and iCloud enabled. This will allow you to debug the issue in a more controlled environment.

Since the crash happens during the execution of NSFetchedResultsController, you may want to try different ways of fetching data, such as using NSFetchRequest directly, to see if it resolves the issue.

Make sure your app is not holding on to any stale NSManagedObject instances that may have been deleted or changed in the background. This can cause unexpected behavior when fetching data.

Keep an eye on the Apple Developer Forums and related resources for any reports of similar issues or workarounds that may be available.

Lastly, if you have identified this as an iOS 16 bug, you should file a bug report with Apple using their Feedback Assistant tool, providing as much information as possible to help them investigate and resolve the issue.

@iAmBowser - We have never seen the crash on any of our devices or connected to Xcode. Only via reports and now users on TestFlight.

  1. Yes it is in CoreData framework, we think it is a framework/Cloudkit issue and have filed a bug report. What the original question states is we are hoping to find a work around.

  2. The issue only occurs with CloudKit enabled which CANNOT be run on simulators.

  3. We doubt it is a database issue as this particular model has been working on many user devices and there are NO relationships, simply Entities.

  4. We have tried 7 builds at this point via TestFlight attempting to use alternate approaches or more delayed approaches to initialize CoreData/Cloudkit. All the devices continue to crash in the same way and nothing we have tried prevents it accept the user turns off using iCloud.

  5. We have tried to use Crashlytics to get log statements as to where it is crashing during start, but it seems to crash too quickly to even get those.

We are stuck

More information. We have managed to get Crashlytics logging to work and these are being sent with FireBase CrashReports. Thus far:

  1. Crashing devices are NOT in low power mode.
  2. Crashing devices are NOT getting any low memory notices.
  3. Crashing devices ARE actually completing the CoreData / Cloudkit setup successfully as far as we can tell and notify the UITableView using CoreData to initialize the FetchResultController. At that point or after the UITableView viewDidLoad we attempt to make a FetchRequest.

It is at this point that some devices (only a small percentage) crash deep in CoreData framework with _computSectionInfo error, like so:

1  CoreFoundation                 0x9908 isEqualToString + 100
2  CoreData                       0xc0760 -[NSFetchedResultsController _computeSectionInfo:error:] + 712
3  CoreData                       0x49c08 __43-[NSFetchedResultsController performFetch:]_block_invoke + 520
4  CoreData                       0x82df8 developerSubmittedBlockToNSManagedObjectContextPerform + 156
5  CoreData                       0x82948 -[NSManagedObjectContext performBlockAndWait:] + 208
6  CoreData                       0x5fb24 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 152
7  CoreData                       0x5da10 -[NSFetchedResultsController performFetch:] + 252
8  iPhemeris                      0x1cf1c -[SavedChartViewController viewDidLoad] + 120 (SavedChartViewController.m:120)

We now understand this issue much better. Working with Testers on devices using Japanese and Foreign languages and making some small changes to better handle Unicode we can reproduce the issue, but do not understand how to fix. We noticed the mismatch between the first character index on this screen shot attached and realized that our code to return the first character was not handling Unicode properly.

We therefore modified the code that returns the first Character of the Name Field and which produces the index of first letters running down the right side to be like so. This code is a method on our NSManagedObject that is the object used as the Entity in the DB for fetching. It has some debug Log statements.

This code crashes if we use the localizedUppercaseString and does not if we remove that?

// Used by NSFetchedResultController Table of Charts by first letter
-(NSString *)nameFirstLetter
{
    if(self.name != nil) {
        //return [[self.name substringToIndex:1] localizedUppercaseString];
        NSString *str = [self.name substringWithRange:[self.name rangeOfComposedCharacterSequenceAtIndex:0]];
        NSLog(@"**** Name:[%@] 1st[%@] Upper[%@]", self.name, str, [str localizedUppercaseString]);
        return [str localizedUppercaseString]; //[[self.name substringWithRange:[self.name rangeOfComposedCharacterSequenceAtIndex:0]] localizedUppercaseString];
    }
    else
        return @"?";
}

It is crashing with a FetchRequest that is initialized using this code below. There is some issue created by doing the localizedUpperCase and the _sectionNameKeyPath that uses that returned value in the FetchRequest

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:_sectionNameKeyPath cacheName:nil];
-(void)initializeFetchedResultsController
{
    // Already inititialized
    if(_fetchedResultsController != nil) return;
    
    // Create and configure a fetch request for Charts
    NSManagedObjectContext *moc = ((iPhemerisAppDelegate *)[[UIApplication sharedApplication] delegate]).coreDataUtil.pc.viewContext;
    if(!moc) {
        NSLog(@"*** SavedChartView MOC NOT READY");
        return;
    }    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Charts" inManagedObjectContext:moc];
    [fetchRequest setEntity:entity];
    
    // Create the sort descriptors array
    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
    NSSortDescriptor *chartTypeDescriptor = [[NSSortDescriptor alloc] initWithKey:@"chartType" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, chartTypeDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    
    // Create and initialize the fetch results controller.
    _sectionNameKeyPath = @"nameFirstLetter";
    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:_sectionNameKeyPath cacheName:nil];
    _fetchedResultsController.delegate = self;
}

Based on the additional information provided, it appears that the crashing issue is related to the localizedUppercaseString method used in the nameFirstLetter method of the NSManagedObject subclass. This subclass is used as the sectionNameKeyPath in the NSFetchedResultsController, which is causing some devices running iOS 16 to crash.

To work around this issue, you can try using a different method to convert the first character of the name string to uppercase. Instead of using localizedUppercaseString, you can use uppercaseStringWithLocale: method.

Here's an example of how you could modify the nameFirstLetter method to use uppercaseStringWithLocale::

-(NSString *)nameFirstLetter
{
    if(self.name != nil) {
        NSString *firstChar = [self.name substringToIndex:1];
        NSString *upperCaseFirstChar = [firstChar uppercaseStringWithLocale:[NSLocale currentLocale]];
        NSLog(@"**** Name:[%@] 1st[%@] Upper[%@]", self.name, firstChar, upperCaseFirstChar);
        return upperCaseFirstChar;
    }
    else {
        return @"?";
    }
}

Here are a few more things you can try to further investigate and potentially fix the crashing issue:

Consider using a different sectionNameKeyPath in the NSFetchedResultsController. If the issue is related to the localizedUppercaseString method used in the nameFirstLetter method, you may be able to work around the issue by using a different key path that doesn't rely on this method. For example, you could use a boolean flag to indicate whether the name starts with a letter or a number, and use that flag as the sectionNameKeyPath.

If none of the above steps resolve the issue, you may need to modify your data model to remove the use of localizedUppercaseString in the NSManagedObject subclass. This may require significant changes to your codebase, so it should only be considered as a last resort.

In the meantime, you may want to consider reaching out to affected users and informing them of the issue and potential workarounds. You could also consider disabling iCloud storage in your app until a fix is found, if that's an option.

iCloud/CoreData Crashing [NSFetchResultsController _computeSectionInfo:error]
 
 
Q