AFHTTPSessionManager not deallocating
Asked Answered
G

3

7

Update

After posting this as an issue to the AFNetworking repo, turns out this is in fact a usage issue on my part. Per the response to my issue:

NSURLSession retains its delegate (i.e. AFURLSessionManager). Call invalidateSessionCancelingTasks: to ensure that sessions finalize and release their delegate.

So, long story short: If you are using AHTTPSessionManager in the manner described below, make sure to call invalidateSessionCancelingTasks: to ensure that sessions finalize and release their delegate

Original Question

I have a subclassed AFHTTPSessionManager called GTAPIClient that I am using to connect to my REST API. I realize the docs state to use as a singleton but there are a few cases where I need to gin up a new instance. However, it seems that whenever I do so, the object is never deallocated. Currently, GTAPIClient literally does nothing except NSLog itself when deallocated. Here's some sample code that demonstrates the behavior

GTAPIClient.m

@implementation GTAPIClient
- (void)dealloc
{
    NSLog(@"Dealloc: %@", self);    
}

@end

GTViewController.m

#import "GTBaseEntityViewController.h"

//Models
#import "GTBaseEntity.h"

//Clients
#import "GTAPIClient.h"

@interface GTBaseEntityViewController ()

@property (nonatomic, weak) GTAPIClient *client;
@property (nonatomic, weak) GTBaseEntity *weakEntity;

@end

@implementation GTBaseEntityViewController

- (IBAction)makeClient:(id)sender {

    self.client = [[GTAPIClient alloc] init];
    NSLog(@"I just made an API client %@", self.client);

    //Another random object assigned to a similar property, just to see what happens.
    self.weakEntity = [[GTBaseEntity alloc] init];
    NSLog(@"I just made a random object %@", self.weakEntity);

}

- (IBAction)checkClient:(id)sender {

    NSLog(@"Client: %@", self.client);
    NSLog(@"Entity: %@", self.weakEntity);

}

@end

NSLog output

Fire makeClient:

//It seems to me that both NSLog's should return (null) as they are assigning to a weak property
2014-06-22 16:41:39.143 I just made an API client <GTAPIClient: 0x10b913680, baseURL: (null), session: <__NSCFURLSession: 0x10b915010>, operationQueue: <NSOperationQueue: 0x10b9148a0>{name = 'NSOperationQueue 0x10b9148a0'}>
2014-06-22 16:41:39.144 I just made a random object (null)

Fire checkClient

//Again, both NSLog's should return null for the two objects. However...client is still around. Also, it's overridden dealloc method never fired.

2014-06-22 16:44:43.722  Client: <GTAPIClient: 0x10b913680, baseURL: (null), session: <__NSCFURLSession: 0x10b915010>, operationQueue: <NSOperationQueue: 0x10b9148a0>{name = 'NSOperationQueue 0x10b9148a0'}>
2014-06-22 16:44:43.723 Entity: (null)

For reference, I am using v2.3.1 of AFNetworking. Compiler is warning me that assigning retained object to weak property will release after assignment - which is correct, and functions as expects with my random object. There is nothing else going on in the app. No other view controllers, no other methods on the GTAPIClient, all singleton functionality is removed. Any thoughts on what I am doing wrong here?

Gathering answered 22/6, 2014 at 20:53 Comment(0)
R
2

Replicating your scenario and running it through Instruments shows that AFURLSessionManagers are retained by the NSURLSessions they create, as AFURLSessionManager acts as the delegate for every NSURLSession created. This creates a retain cycle and thus the AFHTTPSessionManager cannot be released. Whether this is a bug in either library or not a bug at all, I'm not sure. You may want to report it on the AFNetworking GitHub page (https://github.com/AFNetworking/AFNetworking).

Ruprecht answered 23/6, 2014 at 1:36 Comment(1)
Very good. I posted an issue to the repo:(github.com/AFNetworking/AFNetworking/issues/2149)Gathering
F
10

Posting the response from Mattt Thompson here to assist future readers:

NSURLSession retains its delegate (i.e. AFURLSessionManager). Call invalidateSessionCancelingTasks: to ensure that sessions finalize and release their delegate.

If, like many apps, your app uses a singleton Session Manager and one URL Session for your entire app, then you don't need to worry about this.

Fennie answered 23/6, 2014 at 16:1 Comment(0)
R
2

Replicating your scenario and running it through Instruments shows that AFURLSessionManagers are retained by the NSURLSessions they create, as AFURLSessionManager acts as the delegate for every NSURLSession created. This creates a retain cycle and thus the AFHTTPSessionManager cannot be released. Whether this is a bug in either library or not a bug at all, I'm not sure. You may want to report it on the AFNetworking GitHub page (https://github.com/AFNetworking/AFNetworking).

Ruprecht answered 23/6, 2014 at 1:36 Comment(1)
Very good. I posted an issue to the repo:(github.com/AFNetworking/AFNetworking/issues/2149)Gathering
H
1
__weak typeof(manager) weak_manager = manager;
[manager requestWithMethod:method URLString: uri parameters:param
         success:^(NSURLSessionDataTask *task, id responseObject) {
                if (completion) {
                    completion(YES, responseObject, task.response);
                }
                [weak_manager invalidateSessionCancelingTasks:YES];
         }
         failure:^(NSURLSessionDataTask *task, NSError *error) {
                if (completion) {
                    completion(NO, error, task.response);
                }
                [weak_manager invalidateSessionCancelingTasks:YES];
         }];
Hausner answered 22/12, 2018 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.