I've released an app update which does an upgrade of the database ie. executes a script file in the bundle that adds a column to existing table , etc. I've tested this by deploying previous version builds on my device from xcode and then deploying the latest version. The upgrade worked fine.
Yesterday my distribution build got accepted to app store. When I start it up , my nightmare scenario materialized , it fails during DB upgrade! I've checked the distribution build and the upgradeSQL file is there , so it doesn't seem to be a missing resource file all though I'm not sure. I have no idea how I should debug this. What is the difference between a distribution build from app store and a release/debug build deployed from xcode , apart from code signing? Doesn't make sense to me.
This is my crash log and the code that fails:
0 libSystem.B.dylib 0x3141d414 pread + 20
1 libsqlite3.0.dylib 0x303a2154 unixRead + 40
2 libsqlite3.0.dylib 0x303bd7c4 sqlite3PagerAcquire + 3748
3 libsqlite3.0.dylib 0x303c7718 sqlite3BtreeNext + 260
4 libsqlite3.0.dylib 0x303c7b84 sqlite3BtreeNext + 1392
5 libsqlite3.0.dylib 0x304272b8 sqlite3VdbeExec + 38668
6 libsqlite3.0.dylib 0x30428944 sqlite3Step + 504
7 libsqlite3.0.dylib 0x303ecbc4 sqlite3_exec + 600
8 MyApp 0x00046ae4 +[DBUpgradeService executeUpgradeScript:] (DBUpgradeService.m:94)
9 MyApp 0x000469aa +[DBUpgradeService upgradeV1_0ToV1_1] (DBUpgradeService.m:67)
10 MyApp 0x0004687a +[DBUpgradeService upgradeDBIfNecessary] (DBUpgradeService.m:27)
11 MyApp 0x000021ec -[MyAppAppDelegate applicationDidFinishLaunching:] (MyAppAppDelegate.m:49)
12 UIKit 0x30a4ef24 -[UIApplication performInitializationWithURL:asPanel:] + 160
13 UIKit 0x30a57dec -[UIApplication _runWithURL:] + 644
14 Foundation 0x306945a2 __NSFireDelayedPerform + 326
15 CoreFoundation 0x30269d88 CFRunLoopRunSpecific + 2642
16 CoreFoundation 0x30269320 CFRunLoopRunInMode + 44
17 GraphicsServices 0x31567e58 GSEventRunModal + 268
18 UIKit 0x30a4fa6c -[UIApplication _run] + 520
19 UIKit 0x30a591d0 UIApplicationMain + 1132
20 MyApp 0x00002090 main (main.m:20)
21 MyApp 0x0000202c start + 44
+ (BOOL) executeUpgradeScript:(NSString*) scriptName{
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *scriptPath = [resourcePath stringByAppendingPathComponent:scriptName];
NSString* upgradeScript = [NSString stringWithContentsOfFile:scriptPath];
NSArray* lines = [upgradeScript componentsSeparatedByString:@"\n"];
//begin transaction
NSString* begin = [NSString stringWithString:@"BEGIN TRANSACTION"];
sqlite3_exec([DatabaseManager getDatabase], begin.UTF8String , nil , nil , nil);
BOOL failed = NO;
for( NSString* line in lines) {
const char *sql = line.UTF8String;
char* error = nil;
sqlite3_exec([DatabaseManager getDatabase], sql , nil , nil , &error); //THIS LINE FAILS
if(error != nil) {
NSLog([NSString stringWithCString:error]);
failed = YES;
break;
}
}
if(failed){
return NO;
}
else{
NSString* commit = [NSString stringWithString:@"COMMIT"];
sqlite3_exec([DatabaseManager getDatabase], commit.UTF8String , nil , nil , nil);
return YES;
}
}
You aren't allowed to modify files in your application bundle (see epatel's link). As part of your build process, the app gets signed, and modifying files in the bundle will break the signature.
You should be using your application's document directory. You should replace your resourcePath assignment with:
NSString *resourcePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
If the upgrade of the DB takes to long time in the launch phase an app can be kicked out.
One way to resolve such a problem could be to put the upgrade in a NSThread
- (void)upgradeSomething:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Do something here that takes time
// and maybe signal when done with some flag or thing...
[pool release];
}
- (void)awakeFromNib
{
// The usual stuff
// and detach a NSThread for upgrade
[NSThread detachNewThreadSelector:@selector(upgradeSomething:)
toTarget:self
withObject:nil]
}
Read here for reason for keeping the event loop active.
User contributions licensed under CC BY-SA 3.0