我发布了一个应用程序更新,它可以升级数据库,即。在捆绑包中执行一个脚本文件,将列添加到现有表等。我已经通过在xcode上部署我的设备上的先前版本构建然后部署最新版本来测试了这一点。升级工作正常。
昨天我的发布版本被app Store接受了。当我启动它时,我的梦魇场景成为现实,它在数据库升级期间失败了!我已经检查了分发版本,并且升级版本文件就在那里,所以它似乎并不是一个缺少的资源文件,尽管我不确定。我不知道应该怎么调试这个。除了代码签名之外,从app store发布的分发版本和从xcode部署的发布/调试版本有什么区别?对我没有意义。
这是我的崩溃日志和失败的代码:
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;
}
}
答案 0 :(得分:1)
您不能修改应用程序包中的文件(请参阅epatel的link)。作为构建过程的一部分,应用程序将被签名,修改捆绑包中的文件将破坏签名。
您应该使用应用程序的文档目录。您应该使用以下命令替换resourcePath分配:
NSString *resourcePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
答案 1 :(得分:1)
如果数据库的升级在启动阶段需要很长时间,则可以启动应用程序。
解决此类问题的一种方法是将升级置于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]
}
阅读here以了解保持事件循环活动的原因。