AFHTTPSessionManager 未解除分配

Posted

技术标签:

【中文标题】AFHTTPSessionManager 未解除分配【英文标题】:AFHTTPSessionManager not deallocating 【发布时间】:2014-06-22 20:53:59 【问题描述】:

更新

在将其作为问题发布到 AFNetworking 存储库后,事实证明这实际上是我的使用问题。根据对我的问题的回复:

NSURLSession 保留其委托(即 AFURLSessionManager)。调用 invalidateSessionCancelingTasks: 以确保会话完成并释放其委托。

所以,长话短说:如果您以下述方式使用 AHTTPSessionManager,请务必致电 invalidateSessionCancelingTasks: 以确保会话完成并释放其委托

原始问题

我有一个名为GTAPIClient 的子类AFHTTPSessionManager,用于连接到我的REST API。我意识到文档状态可以用作单例,但在某些情况下我需要创建一个新实例。但是,似乎每当我这样做时,对象都不会被释放。目前,GTAPIClient 在释放时除了 NSLog 本身之外什么都不做。 这是一些演示行为的示例代码

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 输出

开火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)

开火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)

作为参考,我使用的是 AFNetworking v2.3.1。编译器警告我,将保留对象分配给弱属性将在分配后释放 - 这是正确的,并且与我的随机对象一样起作用。应用程序中没有其他任何事情发生。没有其他视图控制器,GTAPIClient 上没有其他方法,所有单例功能都被删除。关于我在这里做错了什么有什么想法吗?

【问题讨论】:

【参考方案1】:

在此处发布 Mattt Thompson 的回复以帮助未来的读者:

NSURLSessionretains its delegate(即AFURLSessionManager)。致电invalidateSessionCancelingTasks: 以确保会话完成并释放其委托。

如果您的应用与许多应用一样,为您的整个应用使用单例会话管理器和一个 URL 会话,那么您无需担心这一点。

【讨论】:

【参考方案2】:

复制你的场景并通过 Instruments 运行它表明 AFURLSessionManager 被它们创建的 NSURLSession 保留,因为 AFURLSessionManager 充当每个创建的 NSURLSession 的委托。这会创建一个保留周期,因此无法释放 AFHTTPSessionManager。这是任何一个库中的错误还是根本不是错误,我不确定。您可能想在 AFNetworking GitHub 页面 (https://github.com/AFNetworking/AFNetworking) 上报告它。

【讨论】:

非常好。我向 repo 发布了一个问题:(github.com/AFNetworking/AFNetworking/issues/2149)【参考方案3】:
__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];
         ];

【讨论】:

以上是关于AFHTTPSessionManager 未解除分配的主要内容,如果未能解决你的问题,请参考以下文章

从 StoryBoard 加载的自定义 UITableViewCell 未解除分配

解除控制器后未调用委托

解除B视图时未调用UITableView函数

快速使用 AFHTTPSessionManager

在 UI 自动化测试中解除警报时未调用 UIAlertView 的委托方法“clickedButtonAtIndex”

不允许在解除分配时尝试加载视图控制器的视图,这可能会导致未定义的行为