iOS block中使用self的那麼事
我們在使用block的時候,如果在block中使用self
有可能會迴圈引用,產生記憶體洩漏的問題。
通常,我們如果遇到這種情況,我們會將self
轉換成weak automatic
的變數,這樣就避免了block對sel
f強引用,即:
__weak typeof(self) weakSelf = self;
__weak __typeof__(self) weakSelf = self;
__weak __typeof(self) weakSelf = self;
以上三種寫法,任選一種都是可以的,typeof
就是獲取變數的型別,沒別的深奧的東西。
但是,我在檢視AFNetworking
原始碼的時候發現發現,在有的block中使用self
self
轉化weakSelf
,難道這樣不會引起記憶體洩漏的問題嗎?
為此,我做了相關的測試。講道理,如果存在記憶體洩漏,那麼dealloc
方法就不會被呼叫。
測試一:
@property (copy, nonatomic) dispatch_block_t testBlock;
- (void)viewDidLoad {
[super viewDidLoad];
self.testBlock = ^(){
NSLog(@"%@", [self class]);
};
self.testBlock();
}
這塊我為了簡單,直接使用GCD
typedef void (^dispatch_block_t)(void)
它是一個無引數,無返回值的block。
這個testBlock是控制器(以下用VC代替)的一個屬性。在block中直接使用self
就會造成迴圈引用,Xcode也會做出相應的警告提示:
⚠️
Capturingself
strongly in this block is likely to lead to a retain cycle.
這句話的意思就是說,此處的block
強引用了self
,會存在保留環,即迴圈引用,那麼VC的dealloc
方法也不會被正常呼叫。這個時候我們就需要將其轉化為weakSelf
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self.testBlock = ^(){
NSLog(@"%@", [weakSelf class]);
};
self.testBlock();
}
這樣VC的dealloc
方法也可以正常被呼叫了。
結論:當block直接做為VC的屬性時,如果block內部沒有使用weakSelf
,則會造成迴圈引用,導致記憶體洩漏。
測試二:
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self.testBlock = ^(){
[weakSelf doSomething];
};
self.testBlock();
}
- (void)doSomething {
NSLog(@"%@", [self class]);
}
測試發現VC的dealloc
方法被正常呼叫。
結論:當在block中呼叫一個方法,並且這個方法中直接或者間接的使用self
,不會出現記憶體洩漏的問題。
測試三:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_block_t block = ^(){
[self doSomething];
};
block();
}
- (void)doSomething {
NSLog(@"%@", [self class]);
}
測試發現VC的dealloc
方法被正常呼叫,所以我們在使用GCD
的時候,大部分情況都不需要做轉換。
結論:當block不是self
的屬性時,block記憶體使用self
不會造成記憶體洩漏的問題。
測試四:
- (void)viewDidLoad {
[super viewDidLoad];
Class VC = self.class;
[VC doSomethingWithBlock:^{
[self doSomething];
}];
}
+ (void)doSomethingWithBlock:(dispatch_block_t)block {
if (block) {
block();
}
}
- (void)doSomething {
NSLog(@"%@", [self class]);
}
測試發現VC的dealloc
方法被正常呼叫,我們在使用UIView
有關動畫的類方法時,大部分情況都不需要做轉換。
結論:當使用類方法,並且類方法中用block做引數時,block內部使用self
也不會造成記憶體洩漏的問題。
通過這麼多的測試,我們可以看到,當且僅當block直接或間接的被self
持有時,如果不做weakSelf
轉換,就會有記憶體洩漏的風險。
最後補充一點,同樣在檢視AFNetworking的時候,遇到有時候還需要轉化成strongSelf的情況:
__weak __typeof(self) weakSelf = self;
NSURLSessionDataTask *dataTask = nil;
dataTask = [self.sessionManager GET:request.URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
sf_dispatch_main_async_safely(^{
if (success) {
success((NSHTTPURLResponse *)task.response, responseObject);
}
[strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:task.currentRequest.URL];
if ([strongSelf.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[strongSelf.delegate webViewDidFinishLoad:strongSelf];
}
});
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
sf_dispatch_main_async_safely(^{
if (failure) {
failure(error);
}
});
}];
那麼什麼情況下,需要將weakSelf
轉化成strongSelf
呢 ?
由於__weak
變數的特殊性,會在物件銷燬後自動置為nil
,如果在block中多次需要訪問self
,就需要轉化為strong automatic,確保在block使用期間,self
不會被釋放。
相關推薦
iOS block中使用self的那麼事
我們在使用block的時候,如果在block中使用self有可能會迴圈引用,產生記憶體洩漏的問題。 通常,我們如果遇到這種情況,我們會將self轉換成weak automatic的變數,這樣就避免了block對self強引用,即: __weak typeof
iOS Block 中 迴圈引用的解決
前言: 在iOS 中使用block 時 ,如果稍微不注意,則很容易 導致 迴圈引用 導致記憶體洩漏 二者都無法釋放 。出現記憶體洩漏。 #import <Foundation/Foundation.h> typedefvoid (^EOCNetworkFet
講述Sagit.Framework解決:雙向引用導致的IOS記憶體洩漏(下)- block中任性用self
前言: 發現業務程式碼有一個地方的記憶體沒釋放,原因很也簡單: 在block裡用到了self,造成雙向引用,然後就開始思考怎麼處理這個問題。 常規則思維,就是改程式碼,block不要用到self,或只用self的弱引用。 只是框架這裡特別,有一個特好用的系列,STLastXXX系列,是用巨集定
iOS中self.property 和_property的區別,init和dealloc為何避免用self.property
一、self.property訪問 1、self.property 經過oc訊息派發,可以完成屬性所定義的“記憶體管理語義”, 例如copy屬性; 2、通過屬性訪問,可以設定斷點除錯。 二、_property直接訪問例項變數 1、_property直接訪問例項變
iOS開發-多層巢狀block中如何使用__weak和__strong
1、關於__weak __weak只能在ARC模式下使用,也只能修飾物件(比如NSString等),不能修飾基本資料型別(比如int等) __weak修飾的物件在block中不可以被重新賦值。 __weak只在ARC下使用,可以避免迴圈引用。 __weak修飾物
iOS開發中Block的理解與使用
// 隨機生成的顏色 UIColor *color = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1]; // 第二步 給Blo
精通iOS開發--第15章 Grand Central Dispatch和後臺處理之Block與Self的迴圈引用
Block與Self的迴圈引用 01:眾所周知若self中引用了Block塊,而此Block塊中又引用了Self則會造成迴圈引用,需要提醒的是即使在你的block程式碼中沒有顯式地出現"s
【IOS學習】到底什麼時候才需要在ObjC的Block中使用weakSelf/strongSelf
Objective C 的 Block 是一個很實用的語法,特別是與GCD結合使用,可以很方便地實現併發、非同步任務。但是,如果使用不當,Block 也會引起一些迴圈引用問題(retain cycle)—— Block 會 retain ‘self’,而 ‘self‘
iOS開發中ARC的那點事
在MRC時代,Block會隱式地對進入其作用域內的物件(或者說被Block捕獲的指標指向的物件)加retain,來確保Block使用到該物件時,能夠正確的訪問。 這件事情在下面程式碼展示的情況中要更加額外小心。 MyViewController *myController = [[MyV
Block中weak/strong self的用法
在用到block時,我們經常會有這樣一種用法 //請忽略不重要的程式碼行 __weak __typeof(self)weakSelf = self; blk_t blk = ^() { __strong __typeof(weakSelf)stro
iOS面試題(2.)關於在block中使用weakSelf的討論
問題 我們知道,在使用 block 的時候,為了避免產生迴圈引用,通常需要使用 weakSelf 與 strongSelf,寫下面這樣的程式碼: __weak typeof(self) weakSelf = self; [self doSomeBlockJob:^{
iOS開發中block的寫法簡單整理
約定:用法中的符號含義列舉如下: return_type表示返回的物件/關鍵字等(可以是void,並省略) blockName表示block的名稱 var_type表示引數的型別(可以是void,並省略) varName表示引數名稱 1.1 Blo
ios中self的用法
最近有人問我關於什麼時候用self.賦值的問題, 我總結了一下, 發出來給大家參考. 有什麼問題請大家斧正. 關於什麼時間用self. , 其實是和Obj-c的存取方法有關, 不過網上很多人也都這麼解答的, 那它為什麼和存取方法有關? 怎麼有關的? 並沒有多少人回答
iOS開發中 new與alloc/init的區別 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的區別
專案過程中,想到這幾個概念的區別有些模糊,於是縱觀各種資料,來篇博文為自己記錄下,也為小夥伴們說說我的理解。 [className new] 和 [[className alloc] init] 的區別 1.在實際開發中很少會用到new,一般建立物件咱們看到的全
【程式碼筆記】iOS-在Block中修改外部變數值的
一,程式碼。 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loadin
ios開發中類方法與例項方法區別 以及self有什麼不同
Objective-C裡面既有例項方法也類方法。類方法(Class Method) 有時被稱為工廠方法(Factory Method)或者方便方法(Convenience method)。工廠方法的稱謂明顯和一般意義上的工廠方法不同,從本質上來說,類方法可以獨立於物件而執行,所以在其他的語言裡面類方法有的
iOS 開發中的訊息機制-代理、通知、block
關於代理 1.代理時一種設計模式。 使用場景:如果物件B要監聽物件A裡面發什麼了什麼,使用代理。如果物件A想讓物件B去幹活,使用代理。如果物件A中的按鈕或者cell被點選,要把相應的資料傳遞給物件B,使用代理。例如,我們自定義view裡面的button被點選,需要讓控制器知
IOS中 Block用法進階二 區域性變數和全域性變數在Block中的使用
一、區域性變數與block塊 先看下面程式碼: int number=100; void (^TestBlock)(int)=^(int x){ number=number+x; }; TestBl
iOS開發中地圖與定位
視圖 編寫 aps 簡單 -a 第三方 span spa margin 不管是QQ還是微信的移動client都少不了定位功能,之前在微信demo中沒有加入定位功能,今天就寫個定位的小demo來了解一下定位和地圖的東西。地圖和定位看上去是挺高大上一東西。其有使用方法比
iOS開發中,獲取iOS設備型號
bsp ios設備型號 isequal uid eve ide inf turn res 1、首先要導入頭文件 #import <sys/utsname.h> 2、代碼如下 - (NSString *)getDeviceVersionInfo{