美文网首页
8.iOS开发之block

8.iOS开发之block

作者: 苹果我咬了一口 | 来源:发表于2020-04-09 00:02 被阅读0次

    block简介

    block(闭包)的本质是对象,是带有自动变量(局部变量)的匿名函数。

    block与变量

    值拷贝 会自动生成相应的属性来捕获外界变量,外部局部变量的变化不会影响它的的状态,block内部不能修改变量的值。

    使用__block修饰符可以修改自动变量的值,是跟局部static变量一样指针传递

    全局变量则是直接访问。

    对于捕获ObjC对象,不同于基本类型,Block内部访问了对象类型的auto对象时,如果Block是在栈上,将不会对auto对象产生强引用当Block被拷贝到堆上,Block会调_Block_object_assign函数,根据auto对象的修饰符做出相应的操作;如果Block从堆上移除,会调用block内部的dispose函数,内部会调用_Block_object_dispose函数,这个函数会自动释放引用的auto对象。

    解决block的循环引用

    1.使用最简单的weak关键字修饰 

    (会遇到在block中self还需要使用然而被释放)

    可在block作用域内对weakSelf进行strong修饰的临时变量 weak-strong-dance强弱共舞

    self.name = @"name";

        __weaktypeof(self) weakSelf =self;

        self.block= ^{

            __strongtypeof(weakSelf) strongSelf = weakSelf;

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

                NSLog(@"name:%@",strongSelf.name);

            });

        }

    2.用__block修饰中间者变量使用,并在block中置为nil

     self.name = @"name";     __block ViewController *vc = self;     self.block = ^{         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{             NSLog(@"name:%@",vc.name);             vc = nil;         });     };

    3.使用传参把self传入

    self.name = @"name";     self.block = ^(ViewController *vc){         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{             NSLog(@"name:%@",vc.name);         });     };    

    self.block(self);

    Block与内存管理

    根据Block在内存中的位置分为三种类型:

    NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中。

    NSStackBlock是位于栈区,超出变量作用域,栈上的Block以及  __block变量都被销毁。

    NSMallocBlock是位于堆区,在变量作用域结束时不受影响。

    Block的复制

    在全局block调用copy什么也不做

    在栈上调用copy那么复制到堆上

    在堆上调用block 引用计数增加

    Block从栈中复制到堆的几种情况

    调用Block的copy实例方法时

    Block作为函数返回值返回时

    在带有usingBlock的Cocoa方法或者GCD的API中传递Block时候

    将block赋给带有__strong修饰符的id类型或者Block类型时

    Block的底层原理

    研究工具:clang

    block结构体成员:

    isa,指向所属类的指针,也就是block的类型

    Flags,标志变量,在实现block的内部操作时会用到

    Reserved,保留变量

    FuncPtr,block执行时调用的函数指针

    包含了isa指针(包含isa指针的皆为对象),也就是说block也是一个对象(runtime里面,对象和类都是用结构体表示)。

    相关文章

      网友评论

          本文标题:8.iOS开发之block

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