簡體   English   中英

使用AFNetworking下載多個文件時出現內存壓力問題

[英]Memory pressure issue while downloading multiple files using AFNetworking

在我的應用程序中,我試圖下載數千張圖像(每個圖像最大3mb)和十個視頻(每個視頻最大100mb)並將其保存在Documents Directory中。

為此,我正在使用AFNetworking

在這里,我的問題是, 當我使用慢速wifi(大約4mbps)時,我會成功獲取所有數據,但是如果我在100Mbps wifi下進行相同的下載,則應用程序在下載圖像和內存時會收到內存警告下載視頻時出現壓力問題,然后應用程序崩潰

-(void) AddVideoIntoDocument :(NSString *)name :(NSString *)urlAddress{

    NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlAddress]];
    [theRequest setTimeoutInterval:1000.0];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:name];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Successfully downloaded file to %@", path);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {

        //NSLog(@"Download = %f", (float)totalBytesRead / totalBytesExpectedToRead);

    }];
    [operation start];
}

-(void)downloadRequestedImage : (NSString *)imageURL :(NSInteger) type :(NSString *)imgName{

    NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:imageURL]];
    [theRequest setTimeoutInterval:10000.0];
    AFHTTPRequestOperation *posterOperation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
    posterOperation.responseSerializer = [AFImageResponseSerializer serializer];
    [posterOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        //NSLog(@"Response: %@", responseObject);

        UIImage *secImg = responseObject;
        if(type == 1) { // Delete the image from DB
            [self removeImage:imgName];
        }
        [self AddImageIntoDocument:secImg :imgName];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Image request failed with error: %@", error);
    }];

    [posterOperation start];
}

我根據要下載的視頻和圖像的數量循環播放上面的代碼

該行為背后的原因是什么

兩種情況下,我什至都具有內存分配的屏幕截圖

請幫忙

添加代碼以保存下載的圖像

-(void)AddImageIntoDocument :(UIImage *)img :(NSString *)str{

    if(img) {
        NSData *pngData = UIImageJPEGRepresentation(img, 0.4);
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

        NSString *filePathName =[[paths objectAtIndex:0]stringByAppendingPathComponent:str];
        [pngData writeToFile:filePathName atomically:YES];
    }
    else {
        NSLog(@"Network Error while downloading the image!!! Please try again.");
    }
}

出現這種情況的原因是,您正在將大文件加載到內存中(並且大概發生得足夠快,以至您的應用程序沒有機會響應內存壓力通知)。

您可以通過不將這些下載內容加載到內存中來控制峰值內存使用量,從而減輕這種情況。 下載大文件時,通常最好將它們直接流式傳輸到持久性存儲中。 與AFNetworking做到這一點,你可以設置outputStream中的AFURLConnectionOperation ,它應該直接流的內容,該文件,如

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

NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path          = [documentsPath stringByAppendingPathComponent:[url lastPathComponent]]; // use whatever path is appropriate for your app

operation.outputStream = [[NSOutputStream alloc] initToFileAtPath:path append:NO];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"successful");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"failure: %@", error);
}];

[self.downloadQueue addOperation:operation];

順便說一句,您會注意到我不只是在這些請求上打電話給start 就個人而言,我總是將它們添加到已指定最大並發操作數的隊列中:

self.downloadQueue = [[NSOperationQueue alloc] init];
self.downloadQueue.maxConcurrentOperationCount = 4;
self.downloadQueue.name = @"com.domain.app.downloadQueue";

我認為對於內存使用而言,這並不像使用持久性存儲將結果直接流式傳輸到outputStream那樣重要,但是我發現這是在啟動許多並發請求時管理系統資源的另一種機制。

您可以開始使用NSURLSession的downloadTask。

我認為這可以解決您的問題。

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://someSite.com/somefile.zip"]];
[[NSURLSession sharedSession] downloadTaskWithRequest:request
                                        completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
     {
         // Use location (it's file URL in your system)
     }];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM