AFNetworking 3.0 中的内存泄露
2016-08-26 本文已影响2351人
芙箩娅
前言
打开项目代码,使用leak检测内存泄露的时候被吓坏了(忘了截图了……),满屏幕的红X,101 new leaks 35new leaks 28new leaks ,心想计算是block发生了循环引用也应该不至于这么崩才对吧!
勾选call tree中的 转化call tree 和隐藏系统类库 (2 + 3),定位发生内存泄露的地方,发现都是诸如 [self loadNewData]
[self loadData]
之类的地方,估计就是AFN出问题了。
查询资料后果然如此……
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
使用自定义的NetTool时(即AFNetworking的二次封装),使用了这个manager作为实际的get post 的载体,但是,这个方法很像是一个单例,但确实不是单例,SVProgressHUD才是单例,这个不是,这只是一个类方法!
// AFN中 manager的方法,真的不是单例……
+ (instancetype)manager {
return [[[self class] alloc] initWithBaseURL:nil];
}
- (instancetype)initWithBaseURL:(NSURL *)url {
return [self initWithBaseURL:url sessionConfiguration:nil];
}
因此,如果直接在中间件里面使用这个manager,每次网络请求的时候,都会实例化一个对象出来,后果自然是滚滚而来的泄露了。
解决方法:
把manager封装成一个单例即可,这样每次调用的时候就不会实例化了。(应该是这个思路吧……)
// 在AppDelegate中塞入这样一个单例并暴露类方法,设置请求超时为10秒。
static AFHTTPSessionManager *manager ;
- (AFHTTPSessionManager *)sharedHTTPSession {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 10;
});
return manager;
}
// 再在NetTool中使用这个方法来获取AFHTTPSessionManager 的单例
/** 自定义GET请求 */
+ (void)afnGet:(NSString *)url params:(NSDictionary *)params success:(void(^)(id json))success failure:(void(^)(NSError *error))failure{
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
AFHTTPSessionManager *manager = [app sharedHTTPSession];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
这样使用NetTool做网络请求的时候就不会发生内存泄露了
D4BB6968-744E-4A1E-84CC-B133E61AE54E.png 1.jpg头一次感觉看到绿色的这么爽!嗯……好像哪里不对!