ios - 使用 AFNetworking 下载多个文件时出现内存压力问题

标签 ios objective-c afnetworking memory-pressure

在我的应用程序中,我尝试下载数千张图片(每张图片最大 3mb)和 10 段视频(每张视频最大 100mb)并将其保存在文档目录中。

为此,我使用 AFNetworking

我的问题是,当我使用慢速 wifi(大约 4mbps)时,我成功地获取了所有数据,但是如果我在 wifi 下进行下载,则相同速度为 100mbps 应用程序在下载图像时收到内存警告,在下载视频时收到内存压力问题,然后应用程序崩溃

-(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 执行此操作,您可以设置 AFURLConnectionOperationoutputStream,它应该将内容直接流式传输到该文件,例如

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 重要,但我发现这是在启动许多并发请求时管理系统资源的另一种机制。

关于ios - 使用 AFNetworking 下载多个文件时出现内存压力问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26510256/

相关文章:

ios - 如何使用 Reactive Cocoa 以正确的方式链接信号?

ios - 在 UITableView 中重新排序 Realm 对象

ios - 完成 block 阻止 AFJSONRequestOperation 执行

ios - Cocos2d和iphone 5显示

ios - 无法在 IOS 应用程序中使用自定义字体

ios - uisearchbar 上的清除按钮根本不起作用

ios - 如何解析JSON多数组

ios - AF网络 : Handling of asynchronous get request with AFJSONRequestOperation

ios - iOS 的 Twitter 文本计数无法正常工作

iOS .stringsdict 不工作