I have an app in the app store and am using a logging service to get crash logs and associated log data. I am seeing an intermittent crash (low # of users affected and low #
The solution @lupinglade pretty much worked in my case (VoIP app had when starting up from a reboot), but I would also like to point out that there's a delegate function for AppDelegate that is called when protected data becomes available:
applicationProtectedDataDidBecomeAvailable:
This made it a bit easier to implement the solution in my case.
According to the header file it's available from iOS 4 onwards.
It looks like XJones and I have been able to locate the cause of this. It appears to be an iOS edge-case bug or undocumented behavior. I've filed this under Apple bug ID 12935031.
There is an unaccounted for scenario where an application using Core Location significant location change or region monitoring can fail to launch properly (or have other unintended consequences) due to the fact that as of iOS 5, Core Data stores use data protection (encryption) by default.
Steps to Reproduce:
1) Turn on pass code protection on the device
2) Create an application that starts Significant Location Monitoring or Region Monitoring and keeps it started even when in the background. Ie. An app that uses background significant location change or region monitoring.
3) Wait for the battery on the device to run out (there may be other causes as well)
4) The device will shut down
5) Connect the device to the Mac
6) Once the charge is adequate, the device will boot. Important: Do not unlock device at this time.
7) Exit or enter the monitored range or cause a significant change in location to occur. The device will now automatically relaunch the application, because it registered for Significant Location Monitoring or Region Monitoring
8) However, since the device has not been unlocked by the user (pass code not yet entered), the application will not be able to read any of its protected data files. In a Core Data application, this will cause the persistent store coordinator to fail to add the persistent store file to the managed object context. This will cause the app to crash or depending on the code used by the developer even attempt to reset the database. In other apps it may cause crashes for other reasons as this is an unexpected, undocumented side effect of the data protection feature being turned on by default for Core Data stores in iOS 5 and later.
The solution or workaround until Apple corrects this or at least documents it is to either make sure your application stops monitoring significant location changes/regions in applicationWillTerminate or to turn off the default data protection feature by setting NSFileProtectionNone for the NSFileProtectionKey key in the options dictionary when adding the Core Data store to the persistent store coordinator. to wait for the file store to become available using a while() loop that checks for the protected data to become available. There may be other ways of doing this using KVO, but this method works reliably and is easiest to insert into existing code without reworking your entire application startup process.
Update: looks like just setting that key is not enough if data protection is already active on the store. You have to manually set it:
[[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey] ofItemAtPath:storePath error:nil];
Here's the fix for apps that need background location monitoring, thanks to more input from XJones and a bit more research in Apple's scattered docs:
while(![[UIApplication sharedApplication] isProtectedDataAvailable]) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
}
This code goes in before you attempt to add the store data file to the persistent store coordinator.
Update 2015: You can also set NSPersistentStoreFileProtectionKey to NSFileProtectionNone. This will properly disable file protection (if you don't need it) and just work without requiring any workarounds. The reason it did not work in previous attempts is because the dictionary key I was testing with was incorrect.
Same problem here, still have not been able to find a solution. I've found it seems to be related to having a lock code set on the device. WIthout the lock code I could never reproduce the error, now I have been able to a bunch of times. Console log is:
Error is: Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x1fd80110 {NSUnderlyingException=authorization denied, NSSQLiteErrorDomain=23}
File does exist and not using any encryption.
I just noticed the following notifications in the UIApplication
docs:
UIApplicationProtectedDataDidBecomeAvailable
UIApplicationProtectedDataWillBecomeUnavailable
These are available in iOS 4.0 and later. @lupinglade, I think you need to observe these notifications and only access your protected files (i.e. the store) after you recieve UIApplicationProtectedDataDidBecomeAvailable
.