我有一个应用程序长时间保持打开状态,使用AFNetworking 2.5.0对我们的服务器进行定期API调用。在iOS 8.x上,我看到每次API调用都会导致永久性内存增长,最终导致内存不足崩溃。
我把我的所有代码都煮掉,只使用AFNetworking(以及iOS下面),并且仍然看到了这种内存增长。这是一个非常基本的示例,可以重现我所看到的内容:启动应用并开始练习HTTP GET。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.manager = [AFHTTPRequestOperationManager manager];
// Don't block out text/html extensions, for this example.
_manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil];
[self getApiLoop];
return YES;
}
- (void) getApiLoop {
[_manager GET:@"http://www.stackoverflow.com" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success!");
// Do it again
dispatch_async(dispatch_get_main_queue(), ^{
[self getApiLoop];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failure!");
// Do it again
dispatch_async(dispatch_get_main_queue(), ^{
[self getApiLoop];
});
}];
}
我在iOS 7.0上运行了相同的示例,并没有看到同样类型的失控内存增长。
仪器建议CFNetworking是malloc并且不会在下面释放一些内存。
有任何变通方法吗?我们需要向Apple提交错误吗?
答案 0 :(得分:3)
我找到了一个适合我的代码库的解决方案,很高兴分享它。
AFNetworking 2.x有2个入口点:
我的应用程序需要iOS 6及更高版本,所以我从AFHTTPRequestOperationManager.m开始。 不幸的是,AFHTTPRequestOperationManager.m在iOS 8上显示内存问题,而AFHTTPSessionManager.m没有(!)。不幸的是,这两位经理的软件API完全不同。
我的解决方案是在AFNetworking和我的应用程序的其余部分之间构建一个抽象层,这对我来说有两个目的:一个适用于iOS 6的应用程序,并且在iOS 8上不会因内存而失控;以及一个抽象层,它应该阻止我的团队每次AFNetworking更改时都必须在我的应用程序中编辑每个API调用。
我的应用程序不一定需要访问AFNetworking提供的全部功能,所以我只实现了我需要的功能:
AFNetworking之上的抽象层的一个优点是开发人员可以有效地编辑应用于下面的AFNetworking的更改。例如,当AFNetworking从1.x迁移到2.x时,每个人的应用程序都需要进行大量的代码返工才能与新API保持一致。使用抽象层,您可以选择在一个阻塞点上翻译新的AFNetworking API时保持应用程序的API一致,从而加快开发速度。
我已经在Apache 2.0许可下共享了我的代码: