iOS 8.x + AFNetworking内存增长

时间:2014-11-19 18:11:13

标签: ios afnetworking afnetworking-2

我有一个应用程序长时间保持打开状态,使用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提交错误吗?

1 个答案:

答案 0 :(得分:3)

我找到了一个适合我的代码库的解决方案,很高兴分享它。

AFNetworking 2.x有2个入口点:

  • AFHTTPSessionManager.m - 推荐用于定位iOS 7和iOS 8的应用
  • AFHTTPRequestOperationManager.m - 推荐用于需要返回iOS 6的应用

我的应用程序需要iOS 6及更高版本,所以我从AFHTTPRequestOperationManager.m开始。 不幸的是,AFHTTPRequestOperationManager.m在iOS 8上显示内存问题,而AFHTTPSessionManager.m没有(!)。不幸的是,这两位经理的软件API完全不同。

我的解决方案是在AFNetworking和我的应用程序的其余部分之间构建一个抽象层,这对我来说有两个目的:一个适用于iOS 6的应用程序,并且在iOS 8上不会因内存而失控;以及一个抽象层,它应该阻止我的团队每次AFNetworking更改时都必须在我的应用程序中编辑每个API调用。

我的应用程序不一定需要访问AFNetworking提供的全部功能,所以我只实现了我需要的功能:

  • initWithBaseURL
  • getResponseSerializer - (明确命名,以免我们感到困惑)
  • getRequestSerializer - (明确命名,以免我们感到困惑)
  • setResponseSerializer - (明确命名,以免我们感到困惑)
  • setRequestSerializer - (明确命名,以免我们感到困惑)
  • 使用setValue设置标头:forHTTPHeaderField:
  • GET
  • PUT
  • POST
  • DELETE
  • ...以及取消操作的能力

AFNetworking之上的抽象层的一个优点是开发人员可以有效地编辑应用于下面的AFNetworking的更改。例如,当AFNetworking从1.x迁移到2.x时,每个人的应用程序都需要进行大量的代码返工才能与新API保持一致。使用抽象层,您可以选择在一个阻塞点上翻译新的AFNetworking API时保持应用程序的API一致,从而加快开发速度。

我已经在Apache 2.0许可下共享了我的代码:

https://github.com/eemoss/afnetworking-abstractionlayer-ios