
一.初識block
void (^testBlock)(void) = ^(){
//最基本的block
};
這就是一個(gè)最簡單的block,為了方便初學(xué)者記憶理解,我們再來用熟悉的方法/函數(shù)來對比理解:如果方法/函數(shù)都不熟,我的朋友你路還有點(diǎn)長啊(- -!)
- (void)test{
//最基本的OC對象方法
}
- 第一個(gè)
void:返回值,方法的返回值可以用什么這兒也可以用什么,方法的返回值是干啥的,這也是一樣(如果還理解不了,留言我們交流一下)。 -
^被稱作"脫字符",難記的話你就記?。好看纬霈F(xiàn)block的地方加個(gè)"尖尖"。 -
testBlockblock的變量名,類比方法的方法名,想咋寫咋寫。 -
(void)block語法的參數(shù)列表。類比參數(shù)的參數(shù)列表。注意:iOS11之前沒有參數(shù)寫個(gè)()就可以了。但是iOS11空參數(shù)類型需要寫個(gè)void。否則系統(tǒng)會給你個(gè)黃色警告 -
= ^(){ //最基本的block };這句話就是定義一個(gè)Block,給變量testBlock賦值。同理,方法里能寫啥這就可以寫啥(有個(gè)注意點(diǎn),我在下邊描述)。
最基本的Block介紹完了,和方法一樣我們在實(shí)際應(yīng)用中肯定寫這么個(gè)簡單的玩意兒的,所以我貼一個(gè)稍微復(fù)雜點(diǎn)兒的定義Block代碼(當(dāng)然也就是個(gè)稍微了)
//func:拼接傳入?yún)?shù)并返回
NSString* (^appendParameterBlock)(NSString* , int) = ^(NSString *name,int age){
NSMutableString *mutalStr = [NSMutableString string];
[mutalStr appendFormat:@"%@同學(xué)今年%d歲了",name,age];
return mutalStr;
};
二.如何定義Block
看完上邊也就幾十秒左右,你可能大概有個(gè)印象了。但是你可能現(xiàn)在默寫一個(gè)Block還是有阻礙,這里我介紹兩種方便又好記的方案
1.Xcode自帶代碼塊inline
在寫代碼的地方寫下inline這個(gè)單詞,會出現(xiàn)個(gè)索引,敲回車:
PS:類方法、對象方法中都行
//blockName :block的變量名。相當(dāng)于int a;里邊的a
<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
<#statements#>
};
看到?jīng)]有,舒服又方便。這下你再對比上邊的參數(shù)簡介是不是印象又加深了一點(diǎn)。(作為Coder,上手寫代碼還是很重要的。初始Block的朋友我建議你敲一敲inline,效果更佳)。
2.別名typedef
在你寫宏定義、#import的地方 寫下typedefblock又會出現(xiàn)個(gè)索引,即:
//name :Block類型別名
typedef <#returnType#>(^<#name#>)(<#arguments#>); //索引
typedef void(^myBlock)(void); //示例
這樣也可以通過起別名定義一個(gè)Block類型。
注意:
- typedef僅僅是為Block定義了一個(gè)別名。而在第一節(jié)里邊寫的name是變量名。這點(diǎn)必須認(rèn)識清楚。
- 空參數(shù)列表,還是要寫個(gè)void,同樣也是系統(tǒng)的黃色警告。
- 幫助理解:
就拿上邊那個(gè)最簡單的Block來舉例void (^testBlock)(void) = ^(){};,這里block的類型就是void(^)(void),即空返回值空參數(shù)類型的block。你看這個(gè)東西就有點(diǎn)長,所以我們利用typedef來給他起個(gè)別名。這就是這個(gè)2用法的來源。(如果還是有疑問,留言我們交流一下)
三.使用Block
1. inline定義Block的使用
就用我們那個(gè)稍微稍微復(fù)雜的那個(gè)代碼來舉例使用
NSString *strPrint = appendParameterBlock(@"李華",13);
NSLog(@"%@",strPrint);
- 傳入的參數(shù)類型及順序須與定義時(shí)候的時(shí)候一致
2.別名typedef使用
說到起別名,我們經(jīng)常使用的NSInteger也其實(shí)是個(gè)long類型的別名。(你可以點(diǎn)cmd+左鍵點(diǎn)擊進(jìn)去看下頭文件看一下),既然我們起了個(gè)別名。 那我們就像用NSInteger一樣使用嘛??创a
//1.起別名
typedef void(^myBlock)(int a);
//2.定義或者叫創(chuàng)建一個(gè)變量
myBlock block = ^(int a ){
NSLog(@"%@",a);
};
//3.使用
myBlock(2);
//4.打印結(jié)果:2
四.Block的作用
上邊我在介紹的時(shí)候就是用方法/函數(shù)來類比的。那么作用其實(shí)也一樣,Block就是保存一段代碼,然后再恰當(dāng)?shù)臅r(shí)候調(diào)用。
五.什么時(shí)候使用Block
- 用來傳值。經(jīng)典的就是兩個(gè)頁面之間的逆向傳值。
- 請求網(wǎng)絡(luò)數(shù)據(jù)(延遲),先把展示到控件的代碼先保存到Block,等請求到數(shù)據(jù)的時(shí)候直接調(diào)用Block。經(jīng)典的:AFNetworking
六.拓展:與代理delegate的比較理解
其實(shí)我們通常有一個(gè)說法:
-block相當(dāng)于一個(gè)小弟,當(dāng)我有這個(gè)小弟的時(shí)候,隨叫隨到,想讓他干什么就干什么。再通俗點(diǎn):小弟你幫我先把這段代碼保存起來,等用戶點(diǎn)擊頁面的時(shí)候,再讓小弟去做這個(gè)事情就可以了。
- 代理delegate相當(dāng)于打電話,通知你的代理人讓他去做事情。
當(dāng)然了上邊是一個(gè)很不嚴(yán)謹(jǐn)?shù)念惐?。本文只是為了讓初學(xué)者更快掌握這個(gè)東西。暫且這樣理解著。等掌握了之后,再查資料進(jìn)行深入了解。
七.注意點(diǎn)
通過在.h文件定義一個(gè)block,我們來敘述一些注意點(diǎn)
#import <UIKit/UIKit.h>
typedef void(^PersonBlock)(int a);
@interface Person : NSObject
@property (nonatomic, copy) myBlock block;
@end
- 修飾block請用copy。想知道原因請點(diǎn)擊修飾block為什么要用copy delegate要用weak,查看第六條。
- 定義block類型別名,我們約定:類名+block。當(dāng)然你可以加上你block的功能描述單詞。就好像我們約定OC命名用駝峰語法一樣。
- block可以當(dāng)做對象使用,但他不是一個(gè)對象。所以變量名前邊不要加
*號。 - 如果對象內(nèi)部有一個(gè)Block屬性,而在Block內(nèi)部又訪問了該對象,那么會造成循環(huán)引用。所以遇到問題請弱引用
__weak typeof(p) weakP = p;
本文旨在讓初學(xué)者可以快速上手block,如果掌握以后并且想再深入理解,推薦一篇博客深入理解Block