Block详解

1️⃣Block的修饰

ARC情况下(

ARC是iOS 5推出的新功能,全称叫 ARC(Automatic Reference Counting)。简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

该机能在 iOS 5/ Mac OS X 10.7 开始导入,利用 Xcode4.2 可以使用该机能。简单地理解ARC,就是通过指定的语法,让编译器(LLVM 3.0)在编译代码时,自动生成实例的引用计数管理部分代码。有一点,ARC并不是GC,它只是一种代码静态分析(Static Analyzer)工具。

1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。

解决方法:

新建一个指针(__weak typeof(Target) weakTarget = Target )指向Block代码块里的对象,然后用weakTarget进行操作。就可以解决循环引用问题。

2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。

MRC情况下

用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作。

2️⃣Block的定义格式

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

};

默认情况下,Block内部不能修改外面的局部变量

Block内部可以修改使用__block修饰的局部变量

3️⃣Block的模式

1.无参数无返回值的Block

2.有参数无返回值的Block

3.有参数有返回值的Block

4️⃣Block简单用法举例

①无参数无返回值的Block

/**

*  无参数无返回值的Block

*/

-(void)func1{

    /**

    *  void :就是无返回值

    *  emptyBlock:就是该block的名字

    *  ():这里相当于放参数。由于这里是无参数,所以就什么都不写

    */

    void (^emptyBlock)() = ^(){

        NSLog(@"无参数,无返回值的Block");

    };

    emptyBlock();

}

②有参数无返回值的Block

/**

    *  调用这个block进行两个参数相加

    *

    *  @param int 参数A

    *  @param int 参数B

    *

    *  @return 无返回值

    */

    void (^sumBlock)(int ,int ) = ^(int a,int b){

        NSLog(@"%d + %d = %d",a,b,a+b);

    };

    /**

    *  调用这个sumBlock的Block,得到的结果是20

    */

    sumBlock(10,10);

③有参数有返回值的Block

/**

    *  有参数有返回值

    *

    *  @param NSString 字符串1

    *  @param NSString 字符串2

    *

    *  @return 返回拼接好的字符串3

    */   

    NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){

        return [NSString stringWithFormat:@"%@%@",str1,str2];

    };

    //调用logBlock,输出的是 我是Block

    NSLog(@"%@", logBlock(@"我是",@"Block"));

5️⃣Block结合typedef使用

自己定义一个Block类型,用定义的类型去创建Block,更加简单便捷。

这里举例一个Block回调修改上一下界面的背景颜色。

ViewController1 控制器1,ViewController2 控制器2

控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的背景颜色为红色。

ViewController2的实现

#import

@interface ViewController2 : UIViewController

/**

*  定义了一个changeColor的Block。这个changeColor必须带一个参数,这个参数的类型必须为id类型的

*  无返回值

*  @param id

*/

typedef void(^changeColor)(id);

/**

*  用上面定义的changeColor声明一个Block,声明的这个Block必须遵守声明的要求。

*/

@property (nonatomic, copy) changeColor backgroundColor;

@end

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    //声明一个颜色

    UIColor *color = [UIColor redColor];

    //用刚刚声明的那个Block去回调修改上一界面的背景色

    self.backgroundColor(color);

}

ViewController1的实现

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

ViewController2 *vc =[[ViewController2 alloc]init];

// 回调修改颜色

vc.backgroundColor = ^(UIColor *color){

self.view.backgroundColor = color;

};

[self.navigationController pushViewController:vc animated:YES];

}

=========================================================================================

1.block简介

在 iOS中, block一共分三种。

(1)全局静态 block,不会访问任何外部变量,执行完就销毁。

^{

        NSLog(@"Hello World!");

    }();

(2)保存在栈中的 block,当函数返回时会被销毁,和第一种的区别就是调用了外部变量。

    [UIView animateWithDuration:3 animations:^{


        self.view.backgroundColor = [UIColor redColor];

    }];

(3)保存在堆中的 block,当引用计数为 0 时会被销毁。例如按钮的点击事件,一直存在,即使执行过,也不销毁,因为按钮还可能被点击,持有按钮的View被销毁,它才会被销毁。

#import

typedef void(^ButtonClickBlcok)();

@interface TestView : UIView

@property (nonatomic, copy) ButtonClickBlcok buttonClickBlcok;

@end

#import "TestView.h"

@implementation TestView

- (IBAction)buttonClick:(id)sender {


    if (self.buttonClickBlcok) {

        self.buttonClickBlcok();

    }

}

@end

2.block优点

block的代码可读性更好。因为应用block和实现block的地方在一起。代理的声明和实现就分开来了,在两个类中。代理使用起来也更麻烦,因为要声明协议、声明代理、遵守协议、实现协议里的方法。block不需要声明,也不需要遵守,只需要声明和实现就可以了。

block是一种轻量级的回调,可以直接访问上下文,由于block的代码是内联的,运行效率更高。block就是一个对象,实现了匿名函数的功能。所以我们可以把block当做一个成员变量、属性、参数使用,使用起来非常灵活。像用AFNetworking请求数据和GCD实现多线程,都使用了block回调。

3.block缺点

blcok的运行成本高。block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是引用计数加1,使用完或者block置nil后才销毁。delegate只是保存了一个对象指针(一定要用week修饰delegate,不然也会循环引用),直接回调,没有额外消耗。就像C的函数指针,只多做了一个查表动作。

block容易造成循环引用,而且不易察觉。因为为了blcok不被系统回收,所以我们都用copy关键字修饰,实行强引用。block对捕获的变量也都是强引用,所以就会造成循环引用。

#import "ViewController.h"

typedef void(^TestBlock)(void);

@interface ViewController ()

{

    void (^_testCycleBlock)(void);

}

@end

@implementation ViewController

- (void)viewDidLoad {


    [super viewDidLoad];


    __weak ViewController *weakSelf = self;

    _testCycleBlock = ^{

        /**

          //引发循环引用

          NSLog(@"%@", self);

        */

        //防止循环引用

        NSLog(@"%@", weakSelf);

    };

}

@end

4.如何使用

优先使用block。

如果回调函数很多,多余三个使用代理。

如果回调的很频繁,次数很多,像UITableview,每次初始化、滑动、点击都会回调,使用代理。

  block和代理都各有优缺点,所以我们一定要理解区分使用场景,应用适合的回调方式。优化APP的性能,提高流畅性,从点滴做起。

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

推荐阅读更多精彩内容