-
Apple 官方的建議是,傳進 Block 之前,把 ‘self’ 轉換成 weak automatic 的變量,這樣在 Block 中就不會出現對 self 的強引用。如果在 Block 執行完成之前,self 被釋放了,weakSelf 也會變為 nil。
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomething];
});
clang 的文檔表示,在 doSomething 內,weakSelf 不會被釋放。但,下面的情況除外:__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
});
-
在 doSomething 中,weakSelf 不會變成 nil,不過在 doSomething 執行完成,調用第二個方法 doOtherThing 的時候,weakSelf 有可能被釋放,于是,strongSelf 就派上用場了:
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
});
-
例:雖然在這個方法中在block內部調用了self,但是block不是self的屬性不會形成循環引用
- (void)loadNewData
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
parameters[@"a"] = @"list";
parameters[@"c"] = @"data";
parameters[@"type"] = @(self.type);
[manager GET:basicUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//儲存maxtime
self.maxtime = responseObject[@"info"][@"maxtime"];
// 字典數組 -> 模型數據
self.topics = [XCAllItem mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];
[self.tableView reloadData];
//結束刷新
[self.tableView.mj_header endRefreshing];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[SVProgressHUD showErrorWithStatus:@"網絡錯誤"];
}];
//結束刷新
[self.tableView.mj_header endRefreshing];
}
-
例:這個方法中block內部調用了self.manager是self的屬性,所以直接用self會形成循環引用
-(void)loadNewComments
{
[self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"]= @"dataList";
params[@"c"] = @"comment";
params[@"data_id"] = self.topic.ID;
params[@"hot"] = @1;
__weak typeof(self) weakSelf = self;
[self.manager GET:basicUrl parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if ([responseObject isKindOfClass:[NSArray class]]) {
//沒有評論數據
[self.tableView.mj_header endRefreshing];
return ;
}
//最熱評論
weakSelf.hotComments = [XCComment mj_objectArrayWithKeyValuesArray:responseObject[@"hot"]];
//最新評論
weakSelf.hotComments = [XCComment mj_objectArrayWithKeyValuesArray:responseObject[@"data"]];
[weakSelf.tableView reloadData];
[weakSelf.tableView.mj_header endRefreshing];
//判斷評論數據是否已經加載完全
if (self.latestComments.count >= [responseObject[@"total"] intValue]) {
weakSelf.tableView.mj_footer.hidden = YES;
}
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[weakSelf.tableView.mj_footer endRefreshing];
}];
}
-
__strong 確保在 Block 內,strongSelf 不會被釋放。
-
總結
-
在 Block 內如果需要訪問 self 的方法、屬性、變量,建議使用 weakSelf,weakSelf用會隨著上一級的銷毀一起銷毀。
-
如果在 Block 內需要多次 訪問 self,則需要使用 strongSelf,如果block里面有一些任務即使 該頁面退出了還需要執行完畢的,也需要使用strongSelf
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。