2

Web サービスから一連のデータと PDF ドキュメントをダウンロードする iPad アプリを作成します (データが最初にあり、ドキュメントはバックグラウンドで後でダウンロードされます)。そのために、HTTP(S) リクエスト経由で SOAP を使用します。それは正常に動作し、全体として、アプリは正常に動作しています。問題は、ある時点でダウンロードするドキュメントが多すぎると、アプリがクラッシュすることです。Instruments を使用して、特に NSRegularExpression と NSRunLoop のメモリの問題であることがわかりました。(私はARCを使用しています)

コードを改善して、NSRegularExpression の作成を最適化できました。しかし、NSRunLoop の問題を改善する方法がわかりません。

非同期と同期の両方の HTTP リクエストを試しました。非同期を使用して、ダウンロードが完了するまで待つ必要がありました。sleep()/[NSThread sleepForTimeInterval:] はオプションではないため、使用します

while ( _waitToFinish ) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

同期要求を使用して、Instruments は次のことを明らかにします。

[NSURLConnection sendSynchronousRequest:theRequest returningResponse:&urlResponse error:&error];

また、NSRunLoop の助けを借りて「待機」し、メモリを台無しにします。

これは CoreFoundation または ARC のバグですか?

リクエストが完了するのを待っている間にアイドル状態にする別の方法はありますか?

前もって感謝します。

編集:

「メモリの問題」とは、アプリがメモリを使いすぎてクラッシュする (または iOS によって強制終了される) ことを意味します。

これは Instruments が示すもの 楽器のスクリーンショット です。アプリのダウンロード時間が長くなるほど、パーセンテージが高くなります。

編集:

さらに下に行くと、メモリを台無しにしているのは NSURLConnection であることが明らかになりました。connectionどうやらとreceivedDatatoの設定を忘れているようですnil( URL Loading System Programming Guideを参照)。これにより、メモリ使用量が少し改善されました。

ここで、さらに 2 つの大きなメモリ割り当て操作があります。 ここに画像の説明を入力

これは、Instruments が表示するものに属していると思われるコードです。

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [_receivedData appendData:data];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection {    
    NSString *responseText = [[NSString alloc] initWithBytes:[_receivedData mutableBytes] length:[_receivedData length] encoding:NSUTF8StringEncoding];

    self.lastResponse = responseText;

    responseText = nil;
    connection = nil;
    _receivedData = nil;

    _lastResult = TRUE;
    _waitToFinish = FALSE;
}

コードを改善するために変更できることはありますか?

編集:(「NSRunLoopがiPadのメモリを台無しにする」からタイトルを変更)

編集: メモリを台無しにするのはNSURLConnectionであることを証明するテストアプリを作成しました。次に、Apple Developer Support に連絡しました。

NSURLConnection を使用した繰り返しで大量の PDF をダウンロードしているため、解決策は、@autoreleasepool { .. }繰り返しに を追加し、NSRunLoop.

ありがとう。

4

1 に答える 1

1

CoreFoundationやARCのバグではありません。これはコードのバグです。

実行ループを自分で実行しないでください。を使用するだけ+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]です。completionHandlerリクエストが完了すると、ブロックが呼び出されます。それはあなたが応答を処理するときです。その間、メソッドから戻って、実行ループの実行についてシステムに心配させてください。

とで「これはメモリの問題です」とNSRegularExpression言いNSRunLoopますが、問題が何であるか、またはInstrumentsがどのような証拠を示しているかについては言いません。「問題」について詳しく説明していただければ、お手伝いできるかもしれません。

于 2012-03-01T07:55:48.580 に答える