block浅析

Block 的本质是可以截取自动变量的匿名函数。

一.block的三种定义方式

1.返回值类型(^block的名字)(参数类型) = ^(参数类型和参数名) {};

void(^block)() = ^(){

NSLog(@"调用了block");

};

2.//返回值类型(^block的名字)(参数类型) = ^(参数类型和参数名) {};

//如果有参数,定义的时候,必须要写参数,而且必须要有参数变量名

int(^block)(int) = ^(int a){

return 1;

};

3.系统提供了一个定义block的宏

returnType(^blockName)(parameterTypes) = ^(parameters) {

//        statements

//    };

二.block类型

@property (nonatomic, strong) void(^block)();//这样在类中可以拿到self.block

//当然也可以取别名:

typedef void(^BlockType)();//BlockType不是变量名,而是这种类型的block的别名

//然后就可以这样

@property (nonatomic, strong) BlockType block;

三.block变量的传递

(1)如果是局部变量,Block是值传递

(2)如果是静态变量,全局变量,__block修饰的变量,block都是指针传递


@property (nonatomic, strong) CompletionBlock zfbBlock;

//block只能使用strong,不要使用copy

//因为当使用copy的时候,set方法是调用了copy帮你深拷贝一次,没有这个必要.

//就像NSString一样,他一般都是@"a"这种常量,没必要再去深拷贝一次,所以NSString常量也用strong不用copy.

__weak typeof (&*self) weakSelf= self;

/*

因为block会给内部的强指针对象进行一次强引用,比如常见的传入block中的self进行强引用

并且在self中,block又是strong的,self对block是强引用

所以,你强引用我,我强引用你,谁也不会被释放,就造成了循环引用

所以,为了避免循环引用,我们要在block使用self之前,进行这一步操作:

在block中使用weakSelf,就不会产生循环引用问题了.

使用了__weak修饰符的对象,作用等同于定义为weak的property。自然不会导致循环引用问题.

*/


Block 回调实现

首先解释一下我们例子要实现什么功能(其实是烂大街又最形象的例子):

有两个视图控制器 A 和 B,现在点击 A 上的按钮跳转到视图 B ,并在 B 中的textfield 输入字符串,点击 B 中的跳转按钮跳转回 A ,并将之前输入的字符串

显示在 A 中的 label 上。也就是说 A 视图中需要回调 B 视图中的数据。

我们可以简单地这样思考,需要回调数据的是 A 视图,那么 Block 就应该在 B 中定义,用于获取传入回调数据。

因此我们在 BViewController.h 中定义如下:

//BViewController.h#import

typedefvoid(^CallBackBlcok(NSString*text);

//1@interfaceBViewController:UIViewController

@property(nonatomic,copy)CallBackBlcok callBackBlock;//2

@end

在这里,代码 1 用 typedef 定义了void(^) (NSString *text)的别名为CallBackBlcok。这样我们就可以在代码 2 中,使用这个别名定义一个 Block 类型的变量callBackBlock。

在定义了callBackBlock之后,我们可以在 B 中的点击事件中添加callBackBlock的传参操作:

//BViewController.m

- (IBAction)click:(id)sender {

self.callBackBlock(_textField.text);//1[

self.navigationControllerpopToRootViewControllerAnimated:YES];}

这样我们就可以在想要获取数据回调的地方,也就 A 的视图中调用 block:

// AViewController.m

- (IBAction)push:(id)sender { 

  BViewController *bVC = [self.storyboardinstantiateViewControllerWithIdentifier:@"BViewController"];    bVC.callBackBlock= ^(NSString*text){

// 1NSLog(@"text is %@",text);

self.label.text= text;   

};   

[self.navigationControllerpushViewController:bVC animated:YES];}

代码 1 中,通过对回调将 B 中的数据传递到代码块中,并赋值给 A

中的 label,实现了整个回调过程。

上例是通过将 block 直接赋值给 block 属性,也可以通过方法参数的方式传递 block 块。


关于 Block 的疑惑

到目前为止,一切看起来都很美好(如果你照着上面的例子做的话),功能正常, A 视图中也获取到数据了。但是某些人可能就要说了,你的代码有问题,你的思路有问题,你这是误人子弟。

是的,代码的确还有问题,第一个问题就是循环引用的问题,在 A 视图的block 代码块中:

bVC.callBackBlock= ^(NSString*text){NSLog(@"text is %@",text);self.label.text= text;          };

代码self.label.text = text;,在 Block 中引用 self ,也就是 A ,而 A 创建并引用了 B ,而 B 引用callBackBlock,此时就形成了一个循环引用,而编译器也不会报任何错误,我们需要非常小心这个问题(面试百分百问到我会乱说?)。此时我们通常的解决方法是使用弱引用来解除这个循环:

__weakAViewController*weakSelf =self;    bVC.callBackBlock= ^(NSString*text){NSLog(@"text is %@",text);//        self.label.text = text;weakSelf.label.text= text;    };

第二个问题是我自己对 Block 的理解不到位,我们都知道 Block 能截取自动变量,并且是不能在 Block 块中进行修改的(除非用__block修饰符),但是很明显weakSelf.label.text的值被修改了,并且没有用__block修饰符, 这是为什么呢?因为label是个全局变量,而如果像如下的局部变量a是不能修改的,编译器也会报错:

局部变量

通过这个小例子发现的两个问题,也算是值得了。

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

推荐阅读更多精彩内容

  • Block 的使用有两种:1.独立Block 。2.内联Block 。 《一》独立Block 使用方式 一、定义一...
    乡村小子阅读 301评论 0 0
  • 对block的了解不是特别多,平常用代理用的比较多; Block写法:^(传入参数列){行为主体};Block实体...
    阿基米敬阅读 363评论 3 3
  • block是语言的的扩展功能,它是一种带有自动变量(局部变量)的匿名函数. /******************...
    long2016阅读 230评论 0 1
  • 刚刚落下帷幕的第89届奥斯卡以两段获奖感言的乌龙事件喜泪收官,几家欢喜几家愁,恶搞和唏嘘声在网络上的声势绝对不亚于...
    一碗甜椒阅读 845评论 0 0
  • 学习,模仿,如初来乍到 我欣赏你克服了心魔那一刻,但我忘记了奖赏你,对不起我忽视你了,我只会命令你去追赶别人的脚步...
    在努力生活的小姑娘阅读 141评论 0 1