1

AFNetworking を使用してサーバーからファイルをダウンロードします。コードは次のとおりです。

self.networkQueue = [[[NSOperationQueue alloc] init] autorelease];
[networkQueue setMaxConcurrentOperationCount:3];

for(NSDictionary* fileDictionary in self.syncArray) {
    @autoreleasepool {

        if([[fileDictionary allKeys] containsObject:@"downloadZipURL"]) {
            NSString* downloadPath = [fileDictionary objectForKey:@"downloadZipURL"];
            downloadPath = [downloadPath stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
            NSURLRequest *requestURL = [NSURLRequest requestWithURL:[NSURL URLWithString:downloadPath]];

            NSString* localDestPath = [NSString stringWithFormat:@"%@/%@", [FileUtil userDocumentsDirectory], [downloadPath lastPathComponent]];
            NSString* localTempPath = [NSString stringWithFormat:@"%@.tmp", localDestPath];
            [(NSMutableDictionary*)fileDictionary setObject:localDestPath forKey:@"downloadDestination"];

            AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:requestURL];
            operation.outputStream = [NSOutputStream outputStreamToFileAtPath:localDestPath append:NO];
            operation.userInfo = fileDictionary;

            [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
                if (networkQueue.operationCount == 0)
                {
                    if(hasDownloadError || isCancellingSync) {
                        return ;
                    }

                    [self performSelectorInBackground:@selector(processAllFiles) withObject:nil];

                }

            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                NSLog(@"Error: %@", error);
            }];

            //            [operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
            //                NSLog(@"Sent %lld of %lld bytes, %@", totalBytesWritten, totalBytesExpectedToWrite, localDestPath);
            //                float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
            //                [(NSMutableDictionary*)operation.userInfo setObject:[NSString stringWithFormat:@"Downloading %.0f%%", progress*100] forKey:@"downloadStatus"];
            //                [(NSMutableDictionary*)operation.userInfo setObject:[NSNumber numberWithFloat:progress] forKey:@"downloadProgress"];
            //                [syncViewController onPermitUpdated];
            //            }];

            [networkQueue addOperation:operation];
        }
    }
}

私の問題は、このコードが実行されると、メモリがゆっくりと消費され、決して返されないことです。これらは大きなファイルになる可能性があるため、outputStream を使用しました。

任意の提案をいただければ幸いです。

4

1 に答える 1

-1

頭のてっぺんから-ARCを使用していないことがわかりました。

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:requestURL]

この操作をどこかにリリースしていますか?

 [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
                if (networkQueue.operationCount == 0)
                {
                    if(hasDownloadError || isCancellingSync) {
                        return ;
                    }

                    [self performSelectorInBackground:@selector(processAllFiles) withObject:nil];

                }

ここでは、completionBlock で networkQueue を使用しており、ブロックは networkQueue を保持しています。次に、操作を networkQueue に追加すると、操作が保持され、どちらも割り当て解除されません。networkQueue の弱い変数を作成してみて、それを使用してサイクルを断ち切ります。

これらが機能しない場合は、インストゥルメントを実行し、どのオブジェクトがメモリに残っているか、およびそれらの参照カウントがいつ変更されたかを書き留めます。

于 2013-10-10T11:05:17.660 に答える