我的应用程序需要来自sqlite数据库的数据。它将附带该数据库的一个版本,但我需要定期更新(最有可能每月一次)。通常情况下,我一直在通过我设置的一堆web服务将XML应用程序的其他部分作为XML发送,但现在我正在使用的这个特定数据库非常大(大约20-30 MB)当我尝试以这种方式发送超时错误。更新没有XML的sqlite数据库
我试着把数据库放在我的公司服务器上,然后将它下载到一个NSData
对象中。然后我将该数据对象保存到我的应用程序的Documents目录中。当我重新启动我的应用程序时,出现错误,提示“路径文件看起来不是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上,然后放到模拟器中我的应用程序的Documents文件夹中。当我通过这种方式传输数据库来运行我的应用程序时,它运行时没有任何问题,我可以看到我所有的数据。相反,我完全从模拟器中删除了我的应用程序并重新运行它,所以它会从头开始创建我的数据库。我使用USB驱动器将这个新创建的数据库从我的mac传输到我的服务器上。一旦文件在我的服务器上,我试图在上面的代码块中运行我的“下载更新”,但下次启动我的应用时出现“文件路径看起来不是SQLite数据库”错误时仍然崩溃信息。
从这些测试中,我确信问题不在于我尝试下载的数据库。我的“下载更新”代码中的某些内容正在破坏数据库,但我仍然无法找出原因,也没有找到一种可接受的替代方法,以便在我的应用启动后将我的更新发布给我的用户。
更新2: 我一直在做一些更多的搜索,我已经了解到,用户将需要把用户名和密码来访问我的服务器上的任何文件。我现在认为,我从上面的代码中获得的NSData
实际上是一个身份验证挑战,或者与之相关的东西,这就是为什么当我使用NSFileManager
保存它时,它不会被识别为sqlite数据库。
我发现通过身份验证的最简单的解决方案是here。当我尝试执行NSData *fileData = [NSData dataWithContentsOfURL:url options:NSDataReadingMapped error:&error];
(当然,如链接所示,更改我的url
后),我得到一个错误NSCocoaErrorDomain Code=256
,这只是未知错误。这样做后我的fileData
是nil
。我注意到这篇文章很旧,所以我不知道它是否仍然支持。
我还发现了不同的解决方案,以鉴定问题here使用的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
进行转换,但这是我上面提到的“高级外观语法”之一,我不知道该怎么做。
它不包括在他的例子,但我发现了另一个NSURLConnectionDelegate
方法叫connection:didReceiveAuthenticationChallenge:
here,我认为我可以再补充到从示例代码,这应该解决我的身份验证问题。我感觉如果我只是知道如何打电话fetchURL
我会被设置。有没有人有任何建议,我需要做什么来获得fileData
和error
进入该调用?
感谢您的建议。我在这里看到很多关于JSON的内容,但还没有使用它 - 我会看看它(和你提到的AFHTTPClient)。我认为把我的数据库分成多个文件,但它保证不断增长,所以我应该把它分成多少部分是很难弄清的。我希望找到一条不同的路线,但这可能是唯一的途径。 – GeneralMike 2013-04-23 12:15:24
我希望它适合你。 – HalR 2013-04-23 14:33:59
+1:很好的建议 - 将它分解成碎片可能会有所帮助... – 2013-05-04 06:48:50