咱們在開發中經常會用到函數回調,你能夠用通知來替代回調,可是大多數時候回調是比通知方便的,因此何樂而不爲呢?若是你不知道回調使用的場景,咱們來假設一下:app
1.我如今玩手機函數
2.忽然手機沒有電了spa
3.我只好讓手機開始充電.net
4.充電的過程當中我好無聊,我要去看電視,可是我不會一直看電視,我要等手機電充滿了中止看電視,繼續去玩手機線程
5.我開始看電視指針
6.手機電充好了,我聽到手機響了一下,我不看電視了我繼續去玩手機。orm
這個場景中哪裏跟回調相似呢?哪裏跟通知相似呢?其實咱們能夠認爲手機充好電了經過回調的方式讓我繼續玩手機,也能夠認爲手機充好電了通知我能夠繼續玩手機,而後我主動繼續玩手機。這裏更像通知不像回調。可是換個思惟想,若是手機自己沒有回調機制,那他怎麼能在剛好手機剛充滿的時候響一下呢?blog
先不糾結這個問題,咱們看看若是用block怎樣來實現這樣一個場景:事件
咱們隨便找個控制器寫下如下代碼:ip
[cpp] view plain copy
<span style="font-family:Comic Sans MS; font-size:18px">- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"我在玩手機");
NSLog(@"手機沒電了");
[self chargeMyIphone];
NSLog(@"我在看電視");
}
-(void)chargeMyIphone
{
[NSThread sleepForTimeInterval:10];
NSLog(@"電充好了");
}</span>
注意 這裏我用了NSTread sleep,這樣會讓個人主線程沉睡10秒鐘,這個過程當中我我真的能夠一邊看電視一邊充電嗎?
因此咱們應該讓充電的線程和我看電視的線程錯開執行!這裏咱們就不開新線程了,就讓他10秒以後再執行吧。模擬下:
[cpp] view plain copy
<span style="font-family:Comic Sans MS; font-size:18px">- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"我在玩手機");
NSLog(@"手機沒電了");
[self performSelector:@selector(chargeMyIphone:) withObject:Nil afterDelay:10];
NSLog(@"我在看電視");
}
</span>
改一下這一句代碼後,咱們再看看:
2013-09-17 00:47:54.786 故事版應用[1013:a0b]我在玩手機
2013-09-17 00:47:54.787 故事版應用[1013:a0b]手機沒電了
2013-09-17 00:47:54.787 故事版應用[1013:a0b]我在看電視
2013-09-17 00:48:04.799 故事版應用[1013:a0b]電充好了
看起來沒多大問題,可是咱們還沒寫完咱們的場景呢,咱們想充好電以後繼續玩手機?因此咱們寫在哪兒呢?
若是直接放在看電視後面:
NSLog(@"繼續玩手機");
咱們看看控制檯:
2013-09-17 00:50:12.417 故事版應用[1029:a0b]我在玩手機
2013-09-17 00:50:12.418 故事版應用[1029:a0b]手機沒電了
2013-09-17 00:50:12.419 故事版應用[1029:a0b]我在看電視
2013-09-17 00:50:12.419 故事版應用[1029:a0b]繼續玩手機
2013-09-17 00:50:22.431 故事版應用[1029:a0b]電充好了
呵呵!電都沒充好,你就直接繼續玩了?因此這裏應該是電充好之後 咱們再繼續玩手機?
那麼該怎麼作?咱們能夠寫進充電函數裏嗎?
[cpp] view plain copy
<span style="font-family:Comic Sans MS; font-size:18px">-(void)chargeMyIphone
{
NSLog(@"電充好了");
NSLog(@"繼續玩手機");
}</span>
咱們看看控制檯:
2013-09-17 00:51:43.832 故事版應用[1044:a0b]我在玩手機
2013-09-17 00:51:43.833 故事版應用[1044:a0b]手機沒電了
2013-09-17 00:51:43.833 故事版應用[1044:a0b]我在看電視
2013-09-17 00:51:53.848 故事版應用[1044:a0b]電充好了
2013-09-17 00:51:53.849 故事版應用[1044:a0b]繼續玩手機
看起來沒多大問題啊!可是咱們想一想看,咱們把繼續玩手機這件事情寫在了充電函數的最後?
若是說我每次衝完電都繼續玩手機,這個沒什麼問題!可是若是我每次衝完電以後不老是玩手機怎麼辦呢?
好比有一次我充完電以後想出門逛街!這個很好理解吧,那麼這樣寫就不對了!咱們想讓充電函數最後執行的那一行是能夠變化的。有不少方式能夠作到,可是這裏最好的作法確定是追加一個block替換掉咱們寫死的那句代碼啦!
也就是說我在充電前已經安排好一個充電後的計劃了,今天衝完電繼續玩手機,明天衝完電出門逛街,那麼我每次調用的仍是那個充電函數,只是傳的參數不同而已!咱們不用傳int 1表示玩手機,2表示出門逛街,咱們直接把這兩件事情當作參數傳過去!
明白這一點就知道block的最終奧義啦!因此咱們該改造一下這個函數,爲他加個包含代碼的參數!
[cpp] view plain copy
<span style="font-family:Comic Sans MS; font-size:18px">-(void)chargeMyIphone:(void(^)(void))finishBlock
{
NSLog(@"電充好了");
//NSLog(@"繼續玩手機");
finishBlock();
}</span>
這個追加的參數就是咱們的block了,第一個void表示此block無返回值。(^)爲block type的標誌。第二個(void)表示這個block無參數。finishBlock就是他的名字。無參數無返回類型的匿名函數就是咱們的最簡單的block了!他很是方便咱們用來回調,由於他沒有返回值,沒有參數,就至關於只有內部的可執行代碼!
而咱們將一個固定的事件用一段代碼做爲參數傳了進來,而且以 名字() 形式來觸發它,那麼這個函數的結尾就不會老是玩手機了!那麼他能夠是任何事情!
因此咱們來嘗試調用下這個函數:
可是這裏的參數咱們該怎麼傳呢?咱們經過這種方式傳block參數好像不符合他這的object,因此咱們仍是直接調吧,可是把這一行用dispatch_after包起來~
按一下回車:
而後在中間寫我要作什麼,這裏是出門逛街;
接下來在chargeIphone內部敲dis,而後聯想出來選擇第一個按回車:
而後將時間改成10,把整個方法內的代碼移動進去:
[cpp] view plain copy
<span style="font-family:Comic Sans MS; font-size:18px">- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"我在玩手機");
NSLog(@"手機沒電了");
[self chargeMyIphone:^{
NSLog(@"出去逛街");
}];
NSLog(@"我在看電視");
}
-(void)chargeMyIphone:(void(^)(void))finishBlock
{
double delayInSeconds = 10.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(@"電充好了");
finishBlock();
});
}</span>
如今代碼的結構很是清晰:
充電完成以後 我要去逛街。
充電內部須要耗時10秒。
充電的同時我能夠看電視。
充電完成以後回頭來觸發我block中設置的出去逛街。
這樣設置block的好處我已經說過了,咱們沒有把充電函數內部的實現寫死,也就是說當我完成以後不管作什麼都無所謂,調的地方不一樣,傳不一樣的代碼過去就能夠了,這個跟函數指針相似吧。
咱們來運行一下程序驗證下最後的結果:
2013-09-17 01:17:23.127 故事版應用[1088:a0b]我在玩手機
2013-09-17 01:17:23.129 故事版應用[1088:a0b]手機沒電了
2013-09-17 01:17:23.129 故事版應用[1088:a0b]我在看電視
2013-09-17 01:17:33.130 故事版應用[1088:a0b]電充好了
2013-09-17 01:17:33.131 故事版應用[1088:a0b]出去逛街
徹底驗證了咱們的結論,23秒開始充電 ,看電視,33秒的適合充好電出去逛街。
OK ,最簡單的block咱們就講到這裏,用好他來給你的代碼非寫死吧!DON'T HARD WRITE