1

As the users test my app, he random click the screen very quickly, like a monkey , to into my every detail view controller, because every into my detail vc, the vc will fetch data from the net. And in the real device my app crash. I think this issue is cause by memory leak, because this did not appear in simulator, I test my app in instrument, the screenshoot in below:

In instrument:

The situation:

  1. my main screen, click the every item on the main screen will in to a different detail vc.

  2. detail one vc, every in detail vc, user test will fetch data or click random:

  3. the memory grow to 90.5MB, and did not come down, if use user's test method, if take more long time, will be more than 90.5MB:

I use instrument is not that well, and the memory is most used by AFNetworking, i don't know how to do with this. Someone can give advice? Most thanks in advance.

EDIT

I make the AFHTTPSessionManager to be a singleton, but I found my net request become slowly, does this affect me?

#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
aircraft
  • 25,146
  • 28
  • 91
  • 166
  • @Rob many thanks Rob, I want to know, Every time come to the `detail vc`, I request net use `AFNetworking`, if I pop back to main `vc`, if the `AFHTTPSessionManager ` is be killed in `detail vc` ? or if not , I come to the `detail vc` right now and request the network, if in there I create 2 `AFHTTPSessionManager `? – aircraft Nov 25 '16 at 08:35
  • Yes, if you're instantiating your `AFHTTPSessionManager` inside detail vc, but not saving a reference to it anywhere, yes, a new one will be created each time. It's better to save a reference somewhere (e.g. instantiate at top level view controller and pass it around or have some singleton keep track of this for you or use a static variable that is instantiated only once). – Rob Nov 25 '16 at 16:20

1 Answers1

0

You'll see this behavior if you are instantiating lots of new NSURLSession objects (i.e. which will happen if you instantiate a lot of AFHTTPSessionManager objects).

For example, I wrote a simple program that instantiated 50 separate NSURLSession objects, did a simple data task for each (designated by a "sign post" under the "points of interest", below, all taking place during the region indicated by the green bar), and then immediately releasing them.

You'll see that memory went up by almost 6mb, but after roughly 2 minutes (with absolutely no intervention on my part), it only started reclaiming that memory, returning more than half of the memory previously consumed by all of those session objects. This is a reproducible pattern that I see when issuing multiple session objects.

enter image description here

This can be solved by either calling finishTasksAndInvalidate on the NSURLSession objects, or, better, by making sure your app instantiates only one session object and then uses that same session object every time. Either one of these approaches will dramatically reduce the memory profile of the app (and reusing the same session object is simply more efficient).

In short, I would ensure your detail view controller is not instantiating a new AFHTTPSessionManager object each time. Instantiate it once in your app and reuse it.

Having said that, I wonder if you might also have some other memory problem as my 50 NSURLSession objects only consumed 6mb of memory, and it sounds like you're losing more than that. So, I'd suggest fixing the above, but if you're still seeing memory consumption going up (not necessary shown in Leaks anymore, though), perhaps you have some strong reference cycle or the like. The Xcode 8 "debug memory graph" tool (see How to debug memory leaks when Leaks instrument does not show them?) can be helpful in tracking those issues down.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Hi, rob, i have set the `AFHTTPSessionManager` to `singleton`, but it shows the paging load become slow, does it a ffect me? see my ` edit` – aircraft Dec 01 '16 at 02:28
  • I'm not sure what you mean by "paging load become[s] slow", but the singleton pattern's response time is negligible and your performance issue is undoubtedly something else. In fact, rather than the singleton being slow, I've always found re-using the session manager not only solves memory issues, but is actually faster. You should edit question (or create new question) with [MCVE](http://stackoverflow.com/help/mcve) that illustrates alleged performance issue. But, again, I'm confident the problem rests elsewhere (e.g. previously retrieving cached results, something blocking main queue, etc.) – Rob Dec 01 '16 at 03:24
  • My only observation on your singleton pattern is that I think it safer to keep that `static` defined within the singleton method, e.g. https://gist.github.com/robertmryan/c2ff80356530c4ea2458671ebaba16c7, to avoid ever accidentally referencing that static anywhere but from `sharedHTTPSession`. This has nothing to do with the speed issue, but is safer. – Rob Dec 01 '16 at 03:24
  • By the way, if you're not using `progress` block, it's better to use `nil` than to supply empty block. It should be a fraction faster (though only milliseconds, I'm sure)... – Rob Dec 01 '16 at 03:31