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

Posted

技术标签:

【中文标题】将 SQLite 从一个地方移动到另一个地方:应用程序崩溃和不兼容的类型【英文标题】:Moving SQLite from one place to another: app crash and incompatible type 【发布时间】:2011-02-03 19:12:40 【问题描述】:

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

我正在使用书中的示例,但似乎无法使其正常工作。每次我编译它时,我的应用程序都会崩溃。我有以下警告:“初始化'struct NSURL *'的不兼容的Objective-C类型,预期'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'

【问题讨论】:

【参考方案1】:

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

修复警告;您正在将 NSURL 实例分配给需要 NSString 实例的东西。

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

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


问题似乎出在这两个 与 申请文件目录 返回一个 NSURL 但我告诉它 返回一个 NSString。我可以告诉它 返回一个 NSURL 但这给了我一个 我使用的下一行的问题 stringByAppendingPathComponent。是 有办法解决这个问题吗?

您不能告诉返回 NSURL 的方法改为返回 NSString。类型转换返回值和如下赋值都不起作用:

NSString *documentsDirectory = [self applicationDocumentsDirectory];

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

类似下面的东西应该可以工作:

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

【讨论】:

当然可以。 NSURL 和 NSString 不可互换。编辑您的问题以显示编译错误出现在哪里。 我已更新问题以在调试器控制台中显示输出。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

这样就可以了。

// 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;

【讨论】:

我尝试了您的第一个代码,但无法使其正常工作。它认为该文件已经存在,因此它没有被移动,但我的 TableView 中没有显示任何数据。如何实现其他版本的 applicationDocumentsDirectory 方法? 代码在我的应用程序中有效。执行 nslog 以查看数据库中的实际内容。要使用其他版本,只需找到 applicationDocumentsDirectory 声明并将方法签名更改为 ` + (NSSString *) , and copy code into your implementation file. If you want to still call it on self you'll have to change the + to a - so that it's an instance method instead of a class method but theres no reason not to change it to [iBountyHunterAppDelegate applicationDocumentsDirectory] ​​` 我猜由于您不熟悉objective-c 的基础知识,您可能有一些内存管理问题导致表格视图不显示任何内容。一个关于表格视图的好资源在这里:code.google.com/p/iphone4/downloads/list 这是一本非常好的书的源代码,叫做“高级 ios 4 编程”。如果您在“Head First iPhone Development”方面遇到问题,您可能会考虑购买另一本书。另一个很好的表格视图是“更多 iPhone 3 开发:处理 iPhone SDK”(虽然有点密集)。【参考方案4】:

我收到以下警告:“不兼容的 Objective-C 类型正在初始化 'struct NSURL *',预期为 'struct NSString *'

问题是你正在调用苹果提供的 applicationDocumentsDirectory 方法,该方法返回一个 NSURL。

【讨论】:

是否可以让它返回一个 NSString 或使用带有 NSURL 的 stringByAppendingPathComponent?

以上是关于将 SQLite 从一个地方移动到另一个地方:应用程序崩溃和不兼容的类型的主要内容,如果未能解决你的问题,请参考以下文章

将sqlite文件从一个项目复制到另一个项目

将 sqlite 文件从一个项目复制到另一个项目

使用Objective-c中的进度条将文件从一个地方复制到另一个地方[重复]

核心数据:将对象从一个持久存储移动到另一个

UIButton框架在从一个位置移动到另一个位置后发生了变化

Android - 如何获得从一个地方到另一个地方的估计驾驶时间?