将SQLite从一个地方移动到另一个地方:应用程序崩溃和不兼容的类型

时间:2011-02-03 19:12:40

标签: iphone objective-c sqlite sdk

我开始学习Objective-C并帮助我这样做,我正在使用" Head First iPhone Development"。现在我正在学习SQLite数据库并让它们工作我被告知SQLite文件需要在应用程序的Documents文件夹中,因此我必须移动文件。

我正在使用本书中的示例,但我似乎无法将其付诸实践。每次我编译它我的应用程序崩溃。我有以下警告:"不兼容的Objective-C类型初始化&#struct; NSURL *',期望' struct NSString *'

有没有人有提示如何解决这个问题?

修改

问题似乎是在这两行中,applicationDocumentsDirectory返回一个NSURL,但我告诉它返回一个NSString。我可以告诉它返回一个NSURL,但这给我一个问题,我在下一行使用stringByAppendingPathComponent。有办法解决这个问题吗?

    NSString *documentsDirectory = [self applicationDocumentsDirectory];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"iBountyHunter.sqlite"];

这是应用程序崩溃时调试器控制台输出的内容:

2011-02-04 07:33:42.126 iBountyHunter[591:207] -[NSURL stringByAppendingPathComponent:]: unrecognized selector sent to instance 0x6043f80
2011-02-04 07:33:42.128 iBountyHunter[591:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURL stringByAppendingPathComponent:]: unrecognized selector sent to instance 0x6043f80'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00f87be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x010dc5c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00f896fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00ef9366 ___forwarding___ + 966
    4   CoreFoundation                      0x00ef8f22 _CF_forwarding_prep_0 + 50
    5   iBountyHunter                       0x00001d8e -[iBountyHunterAppDelegate createEditableCopyOfDatabaseIfNeeded] + 107
    6   iBountyHunter                       0x00001f24 -[iBountyHunterAppDelegate application:didFinishLaunchingWithOptions:] + 37
    7   UIKit                               0x002ba1fa -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
    8   UIKit                               0x002bc55e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
    9   UIKit                               0x002c6db2 -[UIApplication handleEvent:withNewEvent:] + 1533
    10  UIKit                               0x002bf202 -[UIApplication sendEvent:] + 71
    11  UIKit                               0x002c4732 _UIApplicationHandleEvent + 7576
    12  GraphicsServices                    0x018bda36 PurpleEventCallback + 1550
    13  CoreFoundation                      0x00f69064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    14  CoreFoundation                      0x00ec96f7 __CFRunLoopDoSource1 + 215
    15  CoreFoundation                      0x00ec6983 __CFRunLoopRun + 979
    16  CoreFoundation                      0x00ec6240 CFRunLoopRunSpecific + 208
    17  CoreFoundation                      0x00ec6161 CFRunLoopRunInMode + 97
    18  UIKit                               0x002bbfa8 -[UIApplication _run] + 636
    19  UIKit                               0x002c842e UIApplicationMain + 1160
    20  iBountyHunter                       0x00001cf8 main + 102
    21  iBountyHunter                       0x00001c89 start + 53
)
terminate called after throwing an instance of 'NSException'

4 个答案:

答案 0 :(得分:1)

  

我正在使用书中的例子   但我似乎无法让它发挥作用。   每次我编译它我的应用程序崩溃。   我有以下警告:   “不兼容的Objective-C类型   初始化'struct NSURL *',   预期'struct NSString *'

修正警告;您正在将NSURL实例分配给需要NSString实例的内容。

或发布警告&导致它的代码行。

如果您的应用程序崩溃,请发布崩溃。


  

问题似乎在于这两个问题   用线   applicationDocumentsDirectory   返回NSURL,但我告诉它   返回一个NSString。我可以告诉它   返回NSURL,但这给了我一个   在我使用的下一行的问题   stringByAppendingPathComponent。是   有办法解决这个问题吗?

你不能告诉一个返回NSURL的方法来代替返回NSString。无论是类型转换返回值还是类似以下的赋值都不起作用:

NSString *documentsDirectory = [self applicationDocumentsDirectory];

编译器在该行上发出警告,因为它已被破坏;你不能像NSString那样对待NSURL。

以下内容应该有效:

NSString *documentsDirectory = [[self applicationDocumentsDirectory] path];

答案 1 :(得分:1)

如果应用程序仍然无法在您的模拟器中运行,请记住从模拟器中删除该应用程序,然后再次构建并运行该应用程序。

您可以使用与真实设备相同的方式从模拟器中删除应用程序。

答案 2 :(得分:0)

  

我有以下警告:“不兼容的Objective-C类型初始化'struct NSURL *',期望'struct NSString *'

问题是您正在调用apple提供的applicationDocumentsDirectory方法,该方法返回NSURL。

答案 3 :(得分:0)

这样就可以了。

// Check the existence of database 
        NSFileManager *mngr = [[NSFileManager alloc] init];

        // If the database doesn't exist in our Document folder we copy it to Documents (this will be executed only the first time we launch the app).
        if (![mngr fileExistsAtPath:[NSString stringWithFormat:@"%@/Documents/db.sqlite", NSHomeDirectory()]]){
            NSString *filePath = [[NSBundle mainBundle] pathForResource:@"db.sqlite" ofType:nil];
            [mngr copyItemAtPath:filePath toPath:[NSString stringWithFormat:@"%@/Documents/db.sqlite", NSHomeDirectory()] error:NULL];
        }
        [mngr release];

这是applicationDocumentsDirectory方法的另一个版本:

+ (NSString*)applicationDocumentsDirectory {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}