Trying to get to the bottom of an issue I\'ve been seeing in production builds and FINALLY was able to reproduce it while testing. Using RestKit v0.23.1, when doing an RKMan
This isn't a problem with RestKit. I've seen this problem frequently and it actually looks like the over-release actually happens in Apple's code. The problem happens when you try to save to a Core Data store and it fails. Core Data reports an error as it should, but that error is mishandled.
I had a few scenarios causing the save failures and this is how I fixed them:
The data store is inaccessible because of the Data Protection API.
Either busy wait and let your app fail to launch like this:
while(![[UIApplication sharedApplication] isProtectedDataAvailable]) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
}
Or disable protection if the data in your store isn't sensitive like this:
[_coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:url
options:@{NSPersistentStoreFileProtectionKey:NSFileProtectionNone}
error:&error];
The important thing is that you don't try to save until you can access the file. If you can re-structure you code to prevent accessing the database when it is inaccessible that is good too. You can use the Data Protection API application delegate methods to trigger that mechanism.
The data store is corrupted - The best thing to do here is to delete the store and start over. Here is a good way to detect a corrupted store using the sqlite library directly.
#import
sqlite3 *dbConnection;
if (sqlite3_open([[url absoluteString] UTF8String], &dbConnection) != SQLITE_OK) {
NSLog(@"[SQLITE] Unable to open database!");
}
sqlite3_stmt *statement = nil;
sqlite3_prepare_v2(dbConnection, "PRAGMA quick_check;", -1, &statement, NULL);
NSString *result = nil;
while (sqlite3_step(statement) == SQLITE_ROW) {
for (int i=0; i
This runs a sqlite PRAGMA query to perform an integrity check. I use quick_check, but you could also use integrity_check if you are willing to wait the extra time. You can tell things are good using [result isEqualToString:@"ok"]