iOS Block的基本使用

例行科普

Block 是 iOS4 之后添加的一种语法结构,也成为闭包,或者匿名函数,在iOS开发过程中应用较多,使用也比较方便,常见于传值、回调等。

1.几种类型的Block

Block的定义方式:

返回类型(^block变量名)(参数列表) = ^(形参列表){};

系统提供了一个定义block的宏,输入inlineBlock就会出现

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
        <#statements#>
};
1.1 无参数无返回值的block
void(^blockName)();//声明
blockName = ^(){
    NSLog(@"调用");
};//实现
blockName();//调用

//当然也可以连一起写,看个人喜好
//void(^blockName)() = ^(){
//    NSLog(@"调用");
//};
1.2 无参数有返回值的block
int(^getNum)() = ^(){
    return 1;
};
NSLog(@"%d", getNum());
1.3 有参数无返回值的block
void(^blockName)(int) = ^(int a){
    NSLog(@"%d", a);
};
blockName(3);
1.4 有参数有返回值的block
int(^addNum)(int, int) = ^(int a, int b){
    return a + b;
};
NSLog(@"%d", addNum(242, 424));
1.5 Block的重命名

block的写法还是比较麻烦的,所以系统提供了一个重命名的功能

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

这样写的话,一个有两个参数,无返回值的block类型就变成了blockType,然后只需要用这个类型声明block就可以了。

@property (strong, nonatomic) blockType aBlock;

2 上面几种只是block的初级用法,下面来点中级的。

2.1 Block做为参数

Block作为参数大家应该不陌生,因为最常用的三方库AFN就使用了这种方式。这里就不贴AFN的源码了,直接仿写一个例子,当然,具体内容并没有实现,只是写了一个思路。

- (void)requestWith:(NSString *)url
               with:(void(^)(id dataSource))success
               with:(void(^)(NSError *error))failure
{
    if (success) {
        success(@"你获取的数据");
    }
    if (failure) {
        failure([NSError new]);// 报错信息
    }
}

//调用
[self requestWith:@"url" with:^(id dataSource) {
    //请求成功
} with:^(NSError *error) {
    //请求失败
}];
2.2 Block作为返回值

Block作为返回值看起来就比较奇怪了,最常见的就是masomry了,对就是那个点来点去的,看起来高大上的语法,也就是链式编程。
先在ViewController里声明了一个属性,来存放数据

@property (nonatomic, assign)int result;

然后写返回block的方法:

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

调用:

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

解释起来应该就是这样的:
self.addNum相当于get方法的调用:[self addNum];
self.addNum返回的是一个block,所以你可以给他一个参数1,于是写成这样:self.addNum(1)
然后block返回的又是self,所以继续调用addNum
如此循环下去.......
Viewcontroller可以换成任何一个类,实现方式是一样的

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

你可以看到,打印出来的a的值是5,也就是说,block获取的是a的值,也就是3,所以当a变成5的时候,block内部打印的值并没有改变。

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

这个应该就不用解释了,和上面是相反的结果,block内部打印的值会随着a的值改变而改变,也就是说block获取的是a的指针。
总结起来就是:
(1)如果是局部变量,Block获取的是值。
(2)如果是静态变量,全局变量, __block修饰的变量,block获取的是指针。
说到这就得说一下这个 __block修饰符了,正常情况下block内部是不允许修改局部变量的值的,但是可以修改静态变量和全局变量,为什么?上面提到了,一种是获取值,一种是获取指针,获取值的当然就不让改了,所以需要在局部变量前加个修饰符 __block:

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

这样block获取的就是指针了,也就可以修改了。

3 Block传值

估计这是提到block第一个就想到的功能了,block可以实现页面间的传值功能,直接上例子。
先在第二个页面的.h文件里声明一个block

typedef void(^block)(NSString);

@interface ViewControllerTwo : UIViewController

@property (strong, nonatomic) block aBlock;

@end

然后写下回调方法

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

然后回到第一个页面引入头文件,写跳转方法

- (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的循环引用

在block内部使用self之前,写上这样一句代码

__weak typeof(self) weakSelf = self;

然后将block使用的self全部替换成weakSelf就可以避免循环引用了。

结语:限于水平,本文只写了一些基本用法和注意事项,如果文中存在错误请指出,我会及时修改。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容