3

250MB 未満のファイルをダウンロードするのに問題はありませんが、250MB 以上の zip ファイルをダウンロードしようとすると、アプリが予告なしにエラーなしでクラッシュします。通じる時もあれば通じない時もあります。リークは、肥大化やメモリの損失がないことを確認します。

また、xcodeでデバッグしているときにのみクラッシュが発生することに気付きました。アプリを実行して、デバッグがないときに大きなファイルをダウンロードすると、問題はありません

大きなファイルをダウンロードする場合、AFNetworking クラスに別の方法でアプローチする必要がありますか?

ここに私のコードがあります

NSURL* url=[BFAppGlobals getServerURL:[M.Properties objectForKey:@"zip_path" ]];
NSMutableURLRequest  *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval:3600];


 AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc]  initWithRequest:request] autorelease];

NSString* writePath=[BFAppGlobals getContentResourcePathForFile:strFile];

[delegate onStartDownload:M];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:writePath append:YES];

[operation setDownloadProgressBlock:^(NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) {

    int b=totalBytesRead ;
    int total=totalBytesExpectedToRead;
    float perc=(float)b/(float)total;
    M.progress=perc;
    [((NSObject*)delegate) performSelectorOnMainThread:@selector(onDataReceviedFromRequest:) withObject:M   waitUntilDone:YES];

}];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

     NSDictionary* params=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:writePath,writeDirectory, M, nil] forKeys:[NSArray arrayWithObjects:@"Path",@"Dir",@"Model", nil]];
    [self performSelectorInBackground:@selector(unzipDownloaded:) withObject:params];


} 
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"fail! %@", [error localizedDescription]);
    [delegate onErrorDownload:M WithError:[error localizedDescription]];
    ActiveModel=nil;
}];

[operation start];



****************************  UPDATE ADDED CRASH LOG ***************************************

    Thread 0 Crashed:
    0   libobjc.A.dylib                 0x37d24fbc objc_msgSend + 16
    1   Foundation                      0x35502508 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 12
    2   CoreFoundation                  0x381aa570 ___CFXNotificationPost_block_invoke_0 + 64
    3   CoreFoundation                  0x381360c8 _CFXNotificationPost + 1400
    4   Foundation                      0x354763f4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 60
    5   Foundation                      0x35477c24 -[NSNotificationCenter postNotificationName:object:] + 24
    6   BFiPad                          0x0006d2fc 0x1000 + 443132
    7   CoreFoundation                  0x3813d224 -[NSObject performSelector:withObject:] + 36
    8   Foundation                      0x35517750 __NSThreadPerformPerform + 344
    9   CoreFoundation                  0x381b2afc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
    10  CoreFoundation                  0x381b22c8 __CFRunLoopDoSources0 + 208
    11  CoreFoundation                  0x381b106e __CFRunLoopRun + 646
    12  CoreFoundation                  0x381344d6 CFRunLoopRunSpecific + 294
    13  CoreFoundation                  0x3813439e CFRunLoopRunInMode + 98
    14  GraphicsServices                0x37f0bfc6 GSEventRunModal + 150
    15  UIKit                           0x31cb473c UIApplicationMain + 1084
    16  BFiPad                          0x00003f72 0x1000 + 12146
    17  BFiPad                          0x00003f30 0x1000 + 12080
4

3 に答える 3

2

これはデバッグモードでのみ発生しているようです。デバッグモードを終了するか、リリース時にさらに実行すると、この問題が解決します

于 2012-05-31T23:45:22.550 に答える
1

この質問は古いことは知っていますが、問題はまだ関連しているように見えるので、とにかく解決策を投稿します。

約 250MB のダウンロード後にクラッシュするという同じ問題があり、数バイトがダウンロードされるたびにダウンロード進行状況ブロックが呼び出され、それが A LOT と呼ばれるという事実が原因であることがわかりました。毎秒何度も。そのため、デリゲート メソッド (おそらく何かを実行する) がここから呼び出されると、かなりのメモリ集約型になる可能性があります。

私の解決策は、ダウンロードの進行状況を追跡し、変更が重要な場合にのみデリゲート メソッドを呼び出すことでした (1% 以上に決定しました)。

[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
    float progress = ((float)totalBytesRead) / totalBytesExpectedToRead;
    if ((progress - totalProgress) > 0.01) {
        totalProgress = progress;
        [delegate updateProgress:progress];
    }
}];

float totalProgressインスタンス変数です。

この修正により、メモリ使用量がクラッシュ時の約 280MB から、アプリが既に使用していた約 30MB に減少しました。つまり、ダウンロード プロセス中に目立ったメモリの増加はありませんでした (メモリではなく、ファイルに直接ダウンロードしていると仮定します)。

于 2013-02-25T07:59:15.610 に答える
1

特に何かに所有されているようには見えないoperationため、メモリに残るという保証はありません。を使用してみてくださいNSOperationQueue(おそらく にアタッチされているAFHTTPClientもので、多くのコードがクリーンアップされます)、アップロードを開始するコントローラーでこれを保持プロパティとして設定してください。

于 2012-05-01T15:57:08.290 に答える