【问题标题】:Memory leaks by click screen, network many times, lead to crash in real device多次点击屏幕、网络导致内存泄漏,导致真机崩溃
【发布时间】:2017-04-09 12:29:36
【问题描述】:

当用户测试我的应用程序时,他像猴子一样快速随机点击屏幕,进入我的每一个细节view controller,因为每一个进入我的细节vcvc 将来自fetch data网。在真实设备中,我的应用程序crash。 我认为这个问题是由memory leak 引起的,因为这没有出现在simulator 中,我在instrument 中测试我的应用程序,下面的screenshoot

在仪器中:

情况:

  1. 我的主屏幕,单击主屏幕上的每个item 将进入不同的详细信息vc

  2. 详一vc,一详一vc,用户测试fetch data或随机点击:

  3. 内存增长到90.5MB,并没有下来,如果使用用户的测试方法,如果时间更长,会超过90.5MB

我用instrument不是很好,内存是AFNetworking用得最多的,不知道怎么办。有人可以给建议吗?非常感谢。

编辑

我将 AFHTTPSessionManager设置为singleton,但我发现我的网络请求变慢了,这对我有影响吗?

#import "Mysevers.h"
#import "AFNetworking.h"
#import "HUD.h"


static AFHTTPSessionManager *requestManager ;

@implementation Mysevers

+ (AFHTTPSessionManager *)sharedHTTPSession{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        requestManager = [AFHTTPSessionManager manager];
        requestManager.requestSerializer.timeoutInterval = 10;
    });
    return requestManager;
}


+(void)AFPOSTWithHud:(BOOL)hud andAddressname:(NSString*)addressName parmas:(NSDictionary*)parmas RequestSuccess:(void(^)(id result))success failBlcok:(void(^)(void))failBlcok
{

    if (hud) {
        //[HUD addHUD];
    
        [SVProgressHUD show];
    }

    AFHTTPSessionManager *requestManager = [Mysevers sharedHTTPSession];

    NSString *urlStr = [NSString stringWithFormat:@"%@%@",BASE_URL,addressName];
    DLog(@"%@",urlStr);

    [requestManager POST:urlStr parameters:parmas progress:^(NSProgress * _Nonnull uploadProgress) {
    
 } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (hud) {
            //[HUD removeHUD];
            [SVProgressHUD dismiss];
        }
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    
        if (error != nil) {
            DLog(@"error==%@",[error localizedDescription]);
            if (hud) {
                //[HUD removeHUD];
                [SVProgressHUD dismiss];
            }
            failBlcok();
        }
    
    
        return ;
    }];


}


+(void)AFGETWithHud:(BOOL)hud andAddressname:(NSString*)addressName parmas:(NSDictionary*)parmas RequestSuccess:(void(^)(id result))success failBlcok:( void(^)(void))failBlcok
{    
    if (hud) {
        //[HUD addHUD];
        [SVProgressHUD show];
    }
    AFHTTPSessionManager *requestManager = [Mysevers sharedHTTPSession];

    NSString *urlStr = [NSString stringWithFormat:@"%@%@",BASE_URL,addressName];

    DLog(@"%@",urlStr);


    [requestManager GET:urlStr parameters:parmas progress:^(NSProgress * _Nonnull downloadProgress) {
    
} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        if (hud) {

            //[HUD removeHUD];
            [SVProgressHUD dismiss];
        }
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        DLog(@"error==%@",[error localizedDescription]);
    
        if (hud) {
            //[HUD removeHUD];
            [SVProgressHUD dismiss];
        }
        failBlcok();
    }];
}


@end

【问题讨论】:

  • @Rob 非常感谢 Rob,我想知道,每次来detail vc,我请求网络使用AFNetworking,如果我弹回主vc,如果@987654345 @ 被detail vc 杀死?或者如果没有,我现在就来detail vc 并请求网络,如果在那里我创建2 AFHTTPSessionManager ?
  • 是的,如果你正在实例化你的 AFHTTPSessionManager 内部细节 vc,但没有在任何地方保存对它的引用,是的,每次都会创建一个新的。最好将引用保存在某处(例如,在顶级视图控制器上实例化并传递它,或者让一些单例为您跟踪这一点,或者使用只实例化一次的静态变量)。

标签: ios memory memory-leaks instruments


【解决方案1】:

如果您实例化大量新的 NSURLSession 对象,您将看到这种行为(即,如果您实例化大量 AFHTTPSessionManager 对象,则会发生这种情况)。

例如,我编写了一个简单的程序,它实例化了 50 个单独的 NSURLSession 对象,为每个对象执行了一个简单的数据任务(由下面“兴趣点”下的“路标”指定,所有这些都发生在绿色条指示的区域),然后立即释放它们。

您会看到内存增加了近 6mb,但大约 2 分钟后(我完全没有干预),它才开始回收该内存,返回所有这些之前消耗的内存的一半以上会话对象。这是我在发布多个会话对象时看到的可重现模式。

这可以通过在 NSURLSession 对象上调用 finishTasksAndInvalidate 来解决,或者更好的是,确保您的应用只实例化一个会话对象,然后每次都使用同一个会话对象。这些方法中的任何一种都将显着减少应用程序的内存配置文件(并且重用相同的会话对象更有效)。

简而言之,我会确保您的详细视图控制器不会每次都实例化一个新的AFHTTPSessionManager 对象。在您的应用中实例化一次并重复使用。

话虽如此,我想知道您是否还有其他内存问题,因为我的 50 个NSURLSession 对象只消耗了 6mb 的内存,听起来您损失的不止这些。因此,我建议修复上述问题,但如果您仍然看到内存消耗在上升(但不再需要在泄漏中显示),也许您有一些强大的参考周期或类似的东西。 Xcode 8“调试内存图”工具(参见How to debug memory leaks when Leaks instrument does not show them?)有助于追踪这些问题。

【讨论】:

  • 嗨,rob,我已将AFHTTPSessionManager 设置为singleton,但它显示分页加载变慢,这对我有影响吗?看我的`编辑`
  • 我不确定您所说的“分页负载变慢”是什么意思,但是单例模式的响应时间可以忽略不计,而您的性能问题无疑是另外一回事。事实上,我一直发现重用会话管理器不仅解决了内存问题,而且实际上速度更快,而不是单例运行缓慢。您应该使用 MCVE 编辑问题(或创建新问题),说明所谓的性能问题。但是,我再次相信问题出在其他地方(例如,以前检索缓存的结果、阻塞主队列的东西等)
  • 我对单例模式的唯一观察是,我认为将 static 定义在单例方法中更安全,例如gist.github.com/robertmryan/c2ff80356530c4ea2458671ebaba16c7,以避免在除 sharedHTTPSession 之外的任何地方意外引用该静态。这与速度问题无关,但更安全。
  • 顺便说一句,如果你不使用progress 块,最好使用nil 而不是提供空块。它应该快一点(尽管我敢肯定只有几毫秒)......
猜你喜欢
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2017-06-09
  • 2013-05-09
  • 2015-07-06
  • 2014-06-07
  • 2013-11-20
  • 2011-10-28
相关资源
最近更新 更多