iOS Block的基本使用

例行科普

Block 是 iOS4 之后添加的一種語(yǔ)法結(jié)構(gòu),也成為閉包,或者匿名函數(shù),在iOS開發(fā)過程中應(yīng)用較多,使用也比較方便,常見于傳值、回調(diào)等。

1.幾種類型的Block

Block的定義方式:

返回類型(^block變量名)(參數(shù)列表) = ^(形參列表){};

系統(tǒng)提供了一個(gè)定義block的宏,輸入inlineBlock就會(huì)出現(xiàn)

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
        <#statements#>
};
1.1 無參數(shù)無返回值的block
void(^blockName)();//聲明
blockName = ^(){
    NSLog(@"調(diào)用");
};//實(shí)現(xiàn)
blockName();//調(diào)用

//當(dāng)然也可以連一起寫,看個(gè)人喜好
//void(^blockName)() = ^(){
//    NSLog(@"調(diào)用");
//};
1.2 無參數(shù)有返回值的block
int(^getNum)() = ^(){
    return 1;
};
NSLog(@"%d", getNum());
1.3 有參數(shù)無返回值的block
void(^blockName)(int) = ^(int a){
    NSLog(@"%d", a);
};
blockName(3);
1.4 有參數(shù)有返回值的block
int(^addNum)(int, int) = ^(int a, int b){
    return a + b;
};
NSLog(@"%d", addNum(242, 424));
1.5 Block的重命名

block的寫法還是比較麻煩的,所以系統(tǒng)提供了一個(gè)重命名的功能

typedef void(^blockType)(int, int);

這樣寫的話,一個(gè)有兩個(gè)參數(shù),無返回值的block類型就變成了blockType,然后只需要用這個(gè)類型聲明block就可以了。

@property (strong, nonatomic) blockType aBlock;

2 上面幾種只是block的初級(jí)用法,下面來點(diǎn)中級(jí)的。

2.1 Block做為參數(shù)

Block作為參數(shù)大家應(yīng)該不陌生,因?yàn)樽畛S玫娜綆?kù)AFN就使用了這種方式。這里就不貼AFN的源碼了,直接仿寫一個(gè)例子,當(dāng)然,具體內(nèi)容并沒有實(shí)現(xiàn),只是寫了一個(gè)思路。

- (void)requestWith:(NSString *)url
               with:(void(^)(id dataSource))success
               with:(void(^)(NSError *error))failure
{
    if (success) {
        success(@"你獲取的數(shù)據(jù)");
    }
    if (failure) {
        failure([NSError new]);// 報(bào)錯(cuò)信息
    }
}

//調(diào)用
[self requestWith:@"url" with:^(id dataSource) {
    //請(qǐng)求成功
} with:^(NSError *error) {
    //請(qǐng)求失敗
}];
2.2 Block作為返回值

Block作為返回值看起來就比較奇怪了,最常見的就是masomry了,對(duì)就是那個(gè)點(diǎn)來點(diǎn)去的,看起來高大上的語(yǔ)法,也就是鏈?zhǔn)骄幊獭?br> 先在ViewController里聲明了一個(gè)屬性,來存放數(shù)據(jù)

@property (nonatomic, assign)int result;

然后寫返回block的方法:

- (ViewController *(^)(int))addNum
{
    return ^(int number){
        _result += number;
        return self;
    };
}

調(diào)用:

self.addNum(1).addNum(2).addNum(3);
NSLog(@"%d", _result);

解釋起來應(yīng)該就是這樣的:
self.addNum相當(dāng)于get方法的調(diào)用:[self addNum];
self.addNum返回的是一個(gè)block,所以你可以給他一個(gè)參數(shù)1,于是寫成這樣:self.addNum(1)
然后block返回的又是self,所以繼續(xù)調(diào)用addNum
如此循環(huán)下去.......
Viewcontroller可以換成任何一個(gè)類,實(shí)現(xiàn)方式是一樣的

2.3 Block對(duì)外部變量的修改
int a = 3;
void(^block)() = ^{
  NSLog(@"%d",a);
};
a = 5;
block();

你可以看到,打印出來的a的值是5,也就是說,block獲取的是a的值,也就是3,所以當(dāng)a變成5的時(shí)候,block內(nèi)部打印的值并沒有改變。

static int a = 3;
void(^block)() = ^{
    NSLog(@"%d",a);
};
a = 5;
block();

這個(gè)應(yīng)該就不用解釋了,和上面是相反的結(jié)果,block內(nèi)部打印的值會(huì)隨著a的值改變而改變,也就是說block獲取的是a的指針。
總結(jié)起來就是:
(1)如果是局部變量,Block獲取的是值。
(2)如果是靜態(tài)變量,全局變量, __block修飾的變量,block獲取的是指針。
說到這就得說一下這個(gè) __block修飾符了,正常情況下block內(nèi)部是不允許修改局部變量的值的,但是可以修改靜態(tài)變量和全局變量,為什么?上面提到了,一種是獲取值,一種是獲取指針,獲取值的當(dāng)然就不讓改了,所以需要在局部變量前加個(gè)修飾符 __block:

__block int b = 7;
void(^block)() = ^{
    b = 20;
};

這樣block獲取的就是指針了,也就可以修改了。

3 Block傳值

估計(jì)這是提到block第一個(gè)就想到的功能了,block可以實(shí)現(xiàn)頁(yè)面間的傳值功能,直接上例子。
先在第二個(gè)頁(yè)面的.h文件里聲明一個(gè)block

typedef void(^block)(NSString);

@interface ViewControllerTwo : UIViewController

@property (strong, nonatomic) block aBlock;

@end

然后寫下回調(diào)方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (self.aBlock) {
        self.aBlock(@"回調(diào)傳值");
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

然后回到第一個(gè)頁(yè)面引入頭文件,寫跳轉(zhuǎn)方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    ViewControllerTwo *VC = [ViewControllerTwo new];
    VC.aBlock = ^(NSString *str){
        NSLog(@"%@", str);
    };
    [self presentViewController: VC animated:YES completion:nil];
}

這樣block傳值就完成了。

4 Block的循環(huán)引用

在block內(nèi)部使用self之前,寫上這樣一句代碼

__weak typeof(self) weakSelf = self;

然后將block使用的self全部替換成weakSelf就可以避免循環(huán)引用了。

結(jié)語(yǔ):限于水平,本文只寫了一些基本用法和注意事項(xiàng),如果文中存在錯(cuò)誤請(qǐng)指出,我會(huì)及時(shí)修改。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容