场景:
登陆时候,用户在极短的时间下载很多的图片资源,并且下载是一个异步的,对接口的请求量没有做并发量的限制
问题一:
在下载的过程中,直接显示下载失败,并且后续所有资源都下载失败,解决办法,通过GCD的semaphore,控制并发量
//type 大于等于0,设置此次for 循环里面的最大并发量
dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(type);
//注意点 for 循环必须在移步线程内
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i < 1000; i++){
dispatch_semaphore_wait(semaphore_t, DISPATCH_TIME_FOREVER);
//模拟耗时异步操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_semaphore_signal(semaphore_t);
});
}
}
问题二:
就算我把并发量调到很低,依然下载资源失败,并报错“iOS 28: No space left on device”
一看发现是内存不足,而且是AF报的,说明af 的内存被干爆了,但是此时我的并发量已经很小了
通过一番查找发现
//最后发现问题就在这儿,发现af的这个方法并不是单例方法,多次调用次方法,会导致内存溢出崩溃
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//解决方法,自己写成单例
AFHTTPSessionManager *manger = [NetWork sharedNetWorkManager].manager;
//自己写一个单例
- (AFHTTPSessionManager *)manager
{
if(!_manager)
{
_manager = [AFHTTPSessionManager manager];
_manager.responseSerializer = [AFJSONResponseSerializer serializer];
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/javascript",@"text/plain", nil];
[_manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
_manager.requestSerializer.timeoutInterval = 18.f;
_manager.operationQueue.maxConcurrentOperationCount = 20;
[_manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
}
return _manager;
}
通过这番操作之后,我就算把并发量改到两百或者更多,也不会出现这个问题,所以大家在使用af的时候,如果你的接口并发量特别高的时候,可以从这两个方面去处理,不然很有可能出现“No space left on device”的情况