ここにトリッキーな質問がありますが、その答えは、私を含む多くのネットワーキングの見習いにとって役立つかもしれません。
コンテキストに関する背景情報:
- オンライン サービスからデータをダウンロードするとします。
- これを非同期で行いたい
- 一度に 1 つのダウンロードを行いたい場合は、前のダウンロードが完了してから別のダウンロードを行うことができます。
これを行う 1 つの優れた方法は、再帰を使用することです。あなたが思いつくことができる一般的な実装の問題は、ネットワーク完了ブロックと自己の間の保持サイクルです。これは、weakSelf 参照ポインターを使用して解決できます。
しかし、再帰呼び出しの保持サイクルはどうですか?
次のように、ダウンロード管理クラスを自己指す再帰スタックを実装しました。
-(void)startNetworkDownloadForObjectAtIndex:(int) anIndex
{
__typeof__(self) __weak weakSelf = self;
NSURL *urlForObjectAtIndex = [SomeClass URLforIndex:anIndex];
[self.downloadManager getResourceAtURL:urlForObjectAtIndex success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (indexOfObjectToDownload < weakself.totalNumberOfObjectsToDownload) [weakSelf startNetworkDownloadForObjectAtIndex:indexOfObjectToDownload+1];
else [weakSelf startDOwnloadTimer];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// response code is in operation.response.statusCode
[weakSelf handleNetworkError:error];
}];
}
-(void)handleNetworkError:error
{
// Do some error handling
[self startNetworkDownloadForObjectAtIndex:self.lastUnsentObjectIndex];
}
-(void)startDownloadTimer
{
if (self.syncEngineTimer) [self.syncEngineTimer invalidate];
self.syncEngineTimer = [NSTimer scheduledTimerWithTimeInterval:kSyncTimeInterval
target:self
selector:@selector(restartNetworkDownload)
userInfo:nil
repeats:NO];
}
-(void)restartNetworkDownload
{
// do some fancy calculations / etc to manage your download
int anIndex = theResultOfYourCalculation;
[self startNetworkDownloadForObjectAtIndex:anIndex];
}
わかりました。これは、複数のネットワーク ダウンロード (たとえば、100 枚のちらつき画像を取得する) の再帰呼び出しの可能性のある例であり、たとえば、1 時間後に新しい画像を取得しようとします。コーディングのタイプミスはご容赦ください。
これは、iOS 5.0 以上の iOS デバイス用の ARC で実行しています。
成功と失敗の完了ブロックへの参照を保持する self.downloadManager を使用するときに、weakSelf 参照ポインターを使用することで、保持サイクルの最初のレベルを明らかに破りました。これはすべて問題なく、楽器によく合います。
ここで、Instruments の割り当てを確認すると、複数のダウンロードに対してダウンロード操作を開始します。器具は漏れを示さない。しかし、ヒープを定期的に保存すると、ヒープがゆっくりと成長しているのがわかります。
割り当てを確認し、コール スタックを確認すると、ブロックが startDownloadTimer を使用して自分自身への参照を保持しているように見えます。
考えられる原因と解決策についての説明は大歓迎です:)