私のアプリには、sqlite データベースからのデータが必要です。このデータベースのバージョンが付属していますが、定期的に更新する必要があります (ほとんどの場合、月に 1 回)。通常、私はアプリの他の部分の更新を、セットアップした一連の Web サービスを介して XML として送信してきましたが、現在取り組んでいるこの特定のデータベースは非常に大きく (約 20 ~ 30 MB)、そのように送信しようとすると、タイムアウトエラーが発生します。
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 フォルダーに置きます。この方法でデータベースを転送してアプリを実行すると、問題なく実行され、すべてのデータを表示できます。
逆に、アプリをシミュレーターから完全に削除して再実行したため、データベースが最初から作成されました。この新しく作成したデータベースを Mac から USB ドライブを使用してサーバーに転送しました。ファイルがサーバーに配置されたら、上記のコード ブロックで「更新のダウンロード」を実行しようとしましたが、次にアプリを起動したときに「パスのファイルは SQLite データベースではないようです」というエラーでクラッシュします。メッセージ。
これらのテストから、ダウンロードしようとしているデータベースに問題があるわけではないと確信しています。「アップデートのダウンロード」コードの何かがデータベースを破損していますが、その理由を突き止めることができず、アプリの起動後にユーザーにアップデートを配信するための受け入れ可能な代替方法も見つかりませんでした。
更新 2: さらに検索を行ったところ、サーバー上のファイルにアクセスするには、ユーザーがユーザー名とパスワードを入力する必要があることがわかりました。NSData
上記のコードから戻ってきたのは、実際には認証の課題、またはそれに関連するものであると信じています。そのため、それを で保存するとNSFileManager
、sqlite DB として認識されません。
認証を通過するために私が見つけた最も簡単な解決策はhereです。私がやろうとすると(もちろん、リンクで提案されているようNSData *fileData = [NSData dataWithContentsOfURL:url options:NSDataReadingMapped error:&error];
に変更した後)、エラーが発生しますが、これは不明なエラーです。私はこれをした後です。この投稿はかなり古いので、まだサポートされているかどうかはわかりません。url
NSCocoaErrorDomain Code=256
fileData
nil
の代わりに を使用して、ここで認証の問題に対する別の解決策も見つけました。これはもっと最近のことですが、この例では、これまであまり見たことのない、より高度な構文が使用されています。例からほとんどコピーして貼り付けることができ、私のプロジェクトはエラーなしでビルドされますが、私の. 私は試したNSURLConnection
dataWithContentsOfURL
fetchURL:withCompletion:failure:
UIViewController
NSError *error;
NSData *fileData;
ExampleDelegate *download = [[ExampleDelegate alloc] init];
[download fetchURL:url withCompletion:fileData failure:&error];
しかし、互換性のないポインターを送信するとビルド エラーが発生します。たとえそれらが何から編集されたとしても、私はストレートNSData
とNSError
asExampleDelegateSuccess
とオブジェクトをそれぞれ渡すことができないと思います。私はおそらくそれらを変換するために何かをしなければなりませんが、そのing は上で言及した「高度な構文」の 1 つであり、何をすべきか本当にわかりません。ExampleDelegateFailure
typedef
fileData
error
typedef
彼の例には含まれていませんが、ここNSURLConnectionDelegate
で呼び出される別のメソッドを見つけました。これを例のコードに追加するだけで、認証の問題を解決できるはずです。呼び方さえわかれば大丈夫だと思います。その電話に出るために私が何をする必要があるかについて誰かアドバイスがありますか?connection:didReceiveAuthenticationChallenge:
fetchURL
fileData
error