我尝试将数据库放在我的公司服务器上,然后将其下载到
NSData
对象中。然后,我将该数据对象保存到我的应用程序文档目录中。当我重新启动应用程序时,会出现错误,提示“路径处的文件似乎不是SQLite数据库”。以下是相关代码。// Download data
NSURL *url = [NSURL URLWithString:@"http://www.mysite.net/download/myDatabase.sqlite"];
NSData *fileData = [[NSData alloc] initWithContentsOfURL:url];
NSLog(@"%@",fileData); // Writes a bunch of 8 character (hex?) strings
// Delete old database
NSError *error;
NSURL *destination = [app applicationDocumentsDirectory];
destination = [destination URLByAppendingPathComponent:@"myDatabase"];
destination = [destination URLByAppendingPathExtension:@"sqlite"];
NSLog(@"destination = %@",destination);
[[NSFileManager defaultManager] removeItemAtPath:[destination path] error:&error];
// Save into correct location
[fileData writeToURL:destination atomically:YES];
//[NSFileManager defaultManager] createFileAtPath:[destination path] contents:fileData attributes:nil]; // I also tried this, it doesn't work either.
有没有更新大型数据库的标准流程供应用程序使用?我觉得我正在尝试的方法不正确,而且还有一种完全不同的方法可以做到这一点,但我无法弄清楚是什么方法。
更新: 我尝试了一些东西来找问题,但是没有任何进展。我将我要从服务器下载的数据库放在了一个USB驱动器上,然后把它放到了我正在开发的Mac电脑上,并将其放到了Simulator中我的应用程序的Documents文件夹中。当我通过这种方式传输数据库运行我的应用程序时,它可以正常运行,我可以看到所有的数据。
相反,我完全从模拟器中删除了我的应用程序,并重新运行它,以便从头开始创建我的数据库。我将这个新建的数据库从我的Mac电脑传输到了我的服务器上。一旦文件在我的服务器上,我就尝试在上面运行我的“下载更新”代码块,但它仍然会在下一次启动我的应用程序时崩溃,并显示“路径上的文件似乎不是SQLite数据库”的错误消息。
通过这些测试,我确信问题不在于我尝试下载的数据库。我的“下载更新”代码中的某些内容正在损坏数据库,但我仍然无法找出原因,也没有找到可接受的替代方法来在我的应用程序启动后向用户提供更新。
更新2:
我进行了更多的搜索,并且了解到用户需要输入用户名和密码才能访问我的服务器上的任何文件。我现在相信,我从上面的代码中获取的NSData
实际上是一个认证挑战或类似于此的内容,这就是为什么当我用NSFileManager
保存它时,它不被识别为sqlite数据库。
我发现的最简单的解决方案是在这里。当我尝试执行NSData *fileData = [NSData dataWithContentsOfURL:url options:NSDataReadingMapped error:&error];
(当然,在更改了我的url
之后),我会收到错误NSCocoaErrorDomain Code=256
,这只是未知错误。做完这个操作后,我的fileData
为nil
。我注意到这篇文章很古老,所以我不知道它是否仍然受支持。
NSURLConnection
而不是dataWithContentsOfURL
。这个例子比较新,但其中有一些更高级的语法使我之前从未见过。我基本上可以从例子中复制粘贴,我的项目能够成功构建,但我不知道如何在我的UIViewController
中正确使用fetchURL:withCompletion:failure:
方法的语法。我尝试了:NSError *error;
NSData *fileData;
ExampleDelegate *download = [[ExampleDelegate alloc] init];
[download fetchURL:url withCompletion:fileData failure:&error];
但是这会导致构建错误,因为发送了不兼容的指针。我认为我不能直接将 NSData
和 NSError
作为分别对应于 ExampleDelegateSuccess
和 ExampleDelegateFailure
对象传递,即使它们是从中 typedef
的。我可能需要对 fileData
和 error
进行一些转换,但是那个 typedef
是我上面提到的 "高级外观语法" 之一,我不太清楚该怎么做。
虽然他的示例中没有包含,但我在这里找到了另一个名为 connection:didReceiveAuthenticationChallenge:
的 NSURLConnectionDelegate
方法,我认为我可以将其添加到示例代码中,这样就可以解决我的身份验证问题。我觉得如果我知道如何调用 fetchURL
,我就可以解决了。有人能给我关于如何将 fileData
和 error
传递给该调用的建议吗?
ExampleDelegate
代码(它在后面创建了其他错误),转而使用 AFNetworking。由于我并不想进行 XML 下载,所以我的做法与你的建议有些不同(请看我的回答)。非常感谢你的帮助! - GeneralMike