1) AFN泄漏展示代码
push 一个控制器, 这个 控制器中有一个网络请求.
- (void)requst:(NSString*)url{
//默认配置
// NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// //AFN3.0+基于封住URLSession的句柄
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
__weak typeof(manager) weakmanager = manager;
// __weak typeof(self) weakSelf = self
// AFURLSessionManager *manager = [AppDelegate sharedManager];
//请求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
//下载Task操作
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
//- block的返回值, 要求返回一个URL, 返回的这个URL就是文件的位置的路径
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [cachesPath stringByAppendingPathComponent:response.suggestedFilename];
return [NSURL fileURLWithPath:path];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"错误信息%@",error);
//设置下载完成操作
// filePath就是你下载文件的位置,你可以解压,也可以直接拿来使用
if ([[NSFileManager defaultManager] fileExistsAtPath:[filePath path]]) {
NSString *zipPath = [filePath path];// 将NSURL转成NSString
}
// [weakmanager invalidateSessionCancelingTasks:YES];
}];
[downloadTask resume];
}
2) 如何查看内存泄漏(2种方式)
防止干扰 控制器释放, 确保控制器100% 释放 , 重写AFN 所在的控制器的dealloc方法
2.1) 直接看对象的方式
2.1.1)点击xcode
2.2.2) 看到1000个对象未释放
通过上述发现AFN 的对象未释放 1000次,就有1000 个manager 相关的对象都没有释放
2.2) instrument 查看
并不是所有的未释放对象都可以instrument 查看
2.3) 泄漏1000次的内存对比
1000次 ,相比一次泄漏 内存5.9M , 如果相关的代码更复杂 ,1000次所耗用 的内存只会更多
3) 内存泄漏修改方式
修改之后
4) 两种解决方法的优缺点
4.1) 取消法的优缺点
- 优点: 一次泄漏也没有 , 对象释放最彻底
- 缺点: 改动很麻烦, 每个都需要修改, 如果对AFN 有封装的话, 修改还是比较方便, AFN 没有封装的话, 改动会有很多缺点
4.2) 单例法的优缺点(官方推荐)
优点:1) 简单易行 改动方便
多个网络请求复用一个AFURLSessionManager,连续发两个网络请求,用Wireshark抓包可以看到,第二次网络请求复用了第一次的TCP连接,没有做三次握手。缺点 : 在某些情况下 一个manager 由于线程的原因 导致这个manager 出问题, 对象逻辑出问题, 所有后续的网络都没法 复现 , app出现过少量ios12的用户网络失败之后 ,再也无法联网, 通过判断多次失败的方式, 重新构建一个manager , AFN的源码 例子 也是以单例的方式, app出现的问题 估计还是其他问题引起
内存泄漏的危害
下面的classA , 60个类对象未释放就会导致1.67M 内存的增加
#import <Foundation/Foundation.h>
#import "ClassB.h"
@class ClassB;
@interface ClassA : NSObject
@property(nonatomic,strong) ClassB *classb;
@end
#import "ClassA.h"
@implementation ClassA
@end
6) demo 的链接
参考文献:
AFN为什么会内存泄漏