最近在寫一個(gè) SDK ,用到了 AFNetwork,其中有一段代碼如下:
...
@property(nonatomic,strong)AFHTTPSessionManager *request;
....
-(void)excute{
...
@weakify(self);
[self.request POST:self.api.APIPath
parameters:self.api.params
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
@strongify(self);
[self handelResponseComplete:responseObject];
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@strongify(self);
[self handelResponseError:error];
}];
...
}
本以為沒問題,結(jié)果每次使用才發(fā)現(xiàn),回調(diào)中的 self 已經(jīng)被釋放了.想了一下,還真是,由于這個(gè)類在使用中是被作為臨時(shí)變量來使用的,生命周期一結(jié)束,沒有強(qiáng)引用,就完蛋了.由于想要先寫一點(diǎn)功能,就干脆直接把@strongify(self);
去掉了,直接上,這次倒不會(huì)被釋放,倒是老覺得會(huì)循環(huán)引用.
始終還是不放心,在-dealoc
方法中加上打印輸出,看看代碼.
突然發(fā)現(xiàn),居然會(huì)正常釋放!
這還了得,趕緊看看是不是哪里弄錯(cuò)了.找了半天好像也沒找到我哪里寫錯(cuò)了,還是看看 AFNetwork 源代碼吧.
,先來看看這個(gè)post
方法
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
[dataTask resume];
return dataTask;
}
再一路跟進(jìn),到了AFURLSessionManager
的這個(gè)方法
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self;
delegate.completionHandler = completionHandler;
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
[self setDelegate:delegate forTask:dataTask];
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
這里創(chuàng)建了一個(gè)代理類,然后把 block 保存在代理類中,而代理類本身通過這個(gè)方法
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
NSParameterAssert(task);
NSParameterAssert(delegate);
[self.lock lock];
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
[delegate setupProgressForTask:task];
[self addNotificationObserverForTask:task];
[self.lock unlock];
}
存放在了一個(gè)字典屬性中.
來捋一捋
self(我自己代碼) -持有> requst(AFHTTPSessionManager)-持有>mutableTaskDelegatesKeyedByTaskIdentifier(字典)-持有>delegate-持有>block-持有>self(我自己代碼中的)
好大一個(gè)環(huán),不過這不還是一個(gè)環(huán)嗎?
不理解.
又來打斷點(diǎn)調(diào)試
看到一個(gè)這個(gè)代碼
有一句[self removeDelegateForTask:task];
這不剛剛和那個(gè)-setDelegate:forTask:
對(duì)應(yīng)嗎?去看看代碼
- (void)removeDelegateForTask:(NSURLSessionTask *)task {
NSParameterAssert(task);
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
[self.lock lock];
[delegate cleanUpProgressForTask:task];
[self removeNotificationObserverForTask:task];
[self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
[self.lock unlock];
}
果然, AFNetwork 在請(qǐng)求結(jié)束后會(huì)自動(dòng)釋放掉 delegate,打破那個(gè)環(huán),所以循環(huán)引用也就不存在了.