我的應用程序需要來自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