3

Webサービスリクエストを介してバイトデータを受信し、それをiOSデバイス上のファイルに書き込みたいという状況があります。以前は、すべてのデータ(データの最後まで)をメモリ変数に追加し、最後にNSStream次の方法を使用してiOSデバイスのファイルにデータを書き込みていました。

stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent

小さなサイズのデータ​​では問題なく動作しますが、問題は、Webサービスを介してデータを受信して​​いる場合、それが大きなチャンク(数MB)になる可能性があり、ファイルに書き込むためにすべてをメモリに収集したくないことです。効率的にNSFileHandleする小さなチャンクサイズのデータ​​を同じファイルに数回書き込むように切り替える必要があると思います。今私の質問は、これを行うための最良のアプローチは何ですか?つまり、バックグラウンドでファイルに書き込むにはどうすればよいNSFileHandleですか?私は次のようなコードを使用します:

 - (void) setUpAsynchronousContentSave:(NSData *) data {

       NSString *newFilePath = [NSHomeDirectory()  stringByAppendingPathComponent:@"/Documents/MyFile.xml"];
     if(![[NSFileManager defaultManager] fileExistsAtPath:newFilePath ]) {
         [[NSFileManager defaultManager] createFileAtPath:newFilePath contents:nil attributes:nil];
     }

     if(!fileHandle_writer) {
         fileHandle_writer = [NSFileHandle fileHandleForWritingAtPath:newFilePath];
     }
     [fileHandle_writer seekToEndOfFile];
     [fileHandle_writer writeData:data];

}

しかし、1〜2 Mbのデータサイズを上記のメソッドに渡す場合、バックグラウンドで実行する必要がありますか?参考までに、私はメインスレッドで書いています。

4

1 に答える 1

8

Grand Central Dispatchを試してみてはいかがでしょうか。

私はそれを試すのにしばらく時間を費やしました。以下は私のやり方です。

Apple のドキュメントによると、プログラムで一度に 1 つのタスクのみを実行する必要がある場合は、「シリアル ディスパッチ キュー」を作成する必要があります。そのため、最初にキューを iVar として宣言します。

dispatch_queue_t queue;

initで、またはViewDidLoad使用してシリアル ディスパッチ キューを作成する

if(!queue)
{
    queue = dispatch_queue_create("yourOwnQueueName", NULL);
}

データが発生したら、メソッドを呼び出します。

- (void) setUpAsynchronousContentSave:(NSData *) data { 

    NSString *newFilePath = [NSHomeDirectory()  stringByAppendingPathComponent:@"/Documents/MyFile.xml"];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    if(![fileManager fileExistsAtPath:newFilePath ]) {
        [fileManager createFileAtPath:newFilePath contents:nil attributes:nil];
    }

    if(!fileHandle_writer) {
        self.fileHandle_writer = [NSFileHandle fileHandleForWritingAtPath:newFilePath];
    }
    dispatch_async( queue ,
                   ^ {
                       // execute asynchronously
                       [fileHandle_writer seekToEndOfFile];
                       [fileHandle_writer writeData:data];
                   }); 
}

最後に、ViewDidUnloadまたはでキューを解放する必要がありますdealloc

if(queue)
{
    dispatch_release(queue);
}

これらのコードを ASIHttp と組み合わせると、うまくいきます。それが役に立てば幸い。

于 2012-01-13T17:14:05.140 に答える