美文网首页
(IOS)Block

(IOS)Block

作者: rightmost | 来源:发表于2018-12-28 14:59 被阅读0次

    1、Block的声明

    格式:

    返回值 (^Block名称) (参数类型);

    举例:

        //无参无返回值的Block

        void (^Block01)();

        //有参无返回值的Block

        void (^Block02)(int);

        //无参有返回值的Block

        int (^Blcok03)();

        //有参有返回值的Block

        int (^Blcok04)(NSString*, NSString *);

    2、Block的定义

    格式:

      返回值类型 (^Block名称) (参数类型) = ^(参数) {

            代码体

        };

    举例:

    //定义无参无返回值的Block

    void (^Block01)() = ^(){

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

        };

    //定义有参无返回值的Block

    void (^Block02)(NSString *) = ^(NSString * name) {

            NSLog(@"%@",name);

        };

    //定义有返回值无参Block(如果没有参数,=后面()可以省略)

    int (^Block03) () = ^() { 

            return 88;

        };

    //定义有参有返回值的Block

    int (^Block04)(int,int) = ^(int a, int b) {

            return a + b;

        };

    Tips:快速生成Block定义:在方法体内输入inlineBlock,选中提示,就会自动生成

    3、Block的调用

        //调用无参无返回值Block

        Block01();

        //调用有参无返回值Block

        Block02(@"lee");

        //调用无参有返回值Block

        int a = Block03();

        //调用有参有返回值Block

        int b = Block04(66,88);

    4、Block使用场景

    传值,回调

    作为方法参数使用

    注意:Block当做参数来使用,并不是马上调用;要在Block做什么事情由外部决定,什么时候做事情由方法内部决定。举个比较常用的例子:

        self.view.transform = CGAffineTransformMakeScale(0.5, 0.5);

        [UIView animateWithDuration:1 animations:^{

            [self.view layoutIfNeeded];

        }];

    作为方法返回值使用(多用于框架封装)

    Blcok作为返回值使用多用于框架封装,比较典型的一个例子就是:Masnoary, 最大的特点就是可以很方便的使用点语法,也就是链式编程。

    5、Block内存管理

    如果Block没有引用外部局部变量,Block就保存在内存的全局区

    只要Block引用了外部局部变量,Block就保存在堆内存中

    Block最好不要使用copy,应该使用strong

    6、解决循环引用

    Block循环引用原因:Block会对里面所有外部局部变量(强指针变量)进行一次强引用,从而导致循环引用。

    //需要将外部的强指针变量弱化__weak typeof(self) weakSelf = self;

    _block = ^{

            NSLog(@"%@",weakSelf);

        };

    如果Block里面有非即时操作(延时操作),由于Block内部是弱指针指向,当{}结束之后就被销毁,从而导致延时操作没办法执行,需要在Block内部将弱化的指针再变为强指针

    __weak typeof(self) weakSelf = self;

    _block = ^{

            NSLog(@"%@",weakSelf);

          //将已经弱化的self指针,转换为强指针以便进行延时操作,否则就执行不到延时操作

            __strong typeof(weakSelf) strongSelf = weakSelf;

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                NSLog(@"%@",strongSelf);

            });

        };

    当 block 本身不被 self 持有,而被别的对象持有,同时不产生循环引用的时候,就不需要使用 weak self 了。最常见的代码就是 UIView 的动画代码,我们在使用 UIView 的 animateWithDuration:animations 方法 做动画的时候,并不需要使用 weak self,因为引用持有关系是:

    UIView 的某个负责动画的对象持有了 block

    block 持有了 self

    因为 self 并不持有 block,所以就没有循环引用产生,因为就不需要使用 weak self 了。

    [UIView animateWithDuration:0.2 animations:^{

        self.alpha = 1;

    }];

    Tips:以下4种情况打印结果分别是多少?

    情况1:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

        int a = 3;

        void (^ block)() = ^{

            NSLog(@"%d",a); 

        };

        a = 5;

        block();

    }

    情况2:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

      static int a = 3;                    ***区别点:静态变量***

        void (^ block)() = ^{

            NSLog(@"%d",a); 

        };

        a = 5;

        block();

    }

    情况3:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

      __block int a = 3;                    ***区别点:被__block修饰***

        void (^ block)() = ^{

            NSLog(@"%d",a); 

        };

        a = 5;

        block();

    }

    情况4:

    __block int a = 3;                      ***区别点:全局变量***

    - (void)viewDidLoad

    {

        [super viewDidLoad];

        void (^ block)() = ^{

            NSLog(@"%d",a); 

        };

        a = 5;

        block();

    }

    总结:

    如果是局部变量(情况1),Block是值传递,打印结果是3;

    如果是静态变量(情况2),全局变量(情况4),被__block修饰(情况3),Block是指针传递(地址传递),打印结果是5;

    相关文章

      网友评论

          本文标题:(IOS)Block

          本文链接:https://www.haomeiwen.com/subject/juoslqtx.html