在這邊用一些例子來做解釋。
__block
在block裡面,要存取外面的變數時,要在變數前面加上這個關鍵字。
舉例來說。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int i = 0; | |
void(^myBlock)() = ^(){ | |
i = i + 1; | |
}; | |
//執行block | |
myBlock(); | |
//印出i值 | |
NSLog(@"%d", i); |
你想要在block去修改外面的變數,如果這樣寫的話會有錯誤,如果要在block裡面去修改變數,則要在前面加上__block關鍵字。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__block int i = 0; | |
void(^myBlock)() = ^(){ | |
i = i + 1; | |
}; | |
//執行block | |
myBlock(); | |
//印出i值 | |
NSLog(@"%d", i); |
__weak與__strong
這兩個會一起做說明,你可以先創一個class,在裡面加入一個方法來做測試,
就像這樣。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface MyObject : NSObject | |
-(void)test; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation MyObject | |
-(void)test{ | |
NSLog(@"A"); | |
} | |
@end |
此時,先做第一個實驗,在block之中去執行剛才那個class的方法,
執行block後,馬上將此物件設為nil,在執行一次block。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MyObject *obj = [MyObject new]; | |
void(^myBlock)() = ^(){ | |
//執行test方法 | |
[obj test]; | |
}; | |
//執行block | |
myBlock(); | |
//將obj設為nil | |
obj = nil; | |
//執行block | |
myBlock(); |
你會發現,明明設為nil了,在block裡面卻還會執行,因為這個block產生了循環引用的問題,那麼該怎麼解決呢,你可以加入__weak關鍵字。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MyObject *obj = [MyObject new]; | |
//使用weak關鍵字 | |
__weak MyObject *weakObj = obj; | |
void(^myBlock)() = ^(){ | |
//使用weakObj執行test方法 | |
[weakObj test]; | |
}; | |
//執行block | |
myBlock(); | |
//將obj設為nil | |
obj = nil; | |
//執行block | |
myBlock(); |
此時,就可以解決循環引用的問題,在這個block裡面並不是強引用,因此當外面設為nil時,block裡面就會變空了。
這樣看起來挺美好的,但是其實還有一個問題,當你的block在執行時,外面有人將設為nil時,你會發現裡面也會變成nil。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MyObject *obj = [MyObject new]; | |
__weak MyObject *weakObj = obj; | |
void(^myBlock)() = ^(){ | |
//先等五秒 | |
sleep(5); | |
NSLog(@"5秒了"); | |
[weakObj test]; | |
}; | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
//用GCD執行你的Block | |
dispatch_async(queue, myBlock); | |
//設為nil | |
obj = nil; |
在block裡面等五秒,然後同時,外面設為nil,五秒後你會發現並沒有執行這個方法,因為已經被設為nil了,你只要在裡面加上__strong關鍵字,在block中就會是強參考
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MyObject *obj = [MyObject new]; | |
__weak MyObject *weakObj = obj; | |
void(^myBlock)() = ^(){ | |
//設為強參考 | |
__strong MyObject *strongObj = weakObj; | |
//先等五秒 | |
sleep(5); | |
NSLog(@"5秒了"); | |
[strongObj test]; | |
}; | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
//用GCD執行你的Block | |
dispatch_async(queue, myBlock); | |
//先等一秒,以免還沒進block就設了 | |
sleep(1); | |
//設為nil | |
obj = nil; |
不過要在設nil之前稍微等一下,以免還沒進去block就被設了XD。
此時你就不怕在block執行時,外面設nil會發生一些怪問題。
可是也許外面設nil,block執行時也會一起變成nil是你需要的效果,你就可以不用加入strong關鍵字。
透過這些實驗應該能稍微了解三者的差異了。
如果這篇文章有任何錯誤或者問題,歡迎提出。
沒有留言:
張貼留言