美文网首页
Block基础

Block基础

作者: Gordon_gc | 来源:发表于2021-11-02 21:12 被阅读0次

    一个最基本的block

    void (^block)(void) = ^(void){
        NSLog(@"这是一个无参数无返回值的block");
    };
    block();//block的灵活性
    
    这边有个思考,如上的block是在储存的哪个区域?

    如果没有深究,凭经验可以说它存在常量区或栈区,因为当前block只是临时变量。
    实际上block存在堆区,因为在当前的ARC环境下,block一旦定义出来,编译器就会自动把栈上的block copy到堆里面。
    这边再思考一下,block是用什么修饰呢?你可能说copy,那strong是否可以呢?其实strong也是可以的,在当前的arc下,其实已经没有什么区别。

    block的分类

    首先了解一下几个存储区域:
    • 代码段:写的代码都存在这边
    • 数据区(常量区):存放全局变量,NSGlobalBlock存放在这边
    • 栈区:存放局部变量,不需要程序员管理,系统自动分配,自动销毁,NSStackBlock存放在这
    • 堆区:存放我们自己alloc出来的对象,动态分配内存,需要程序员自己申请内存,自己管理,NSMallocBlock存放在这
    // -| NSGlobalBlock
    // 没有引用auto变量
    void (^block)(void) = ^(void){
        NSLog(@"没有引用auto变量");
    }
    NSLog(@"%@",block); //这边用%@ --> block是一个对象
    
    // -| NSStackBlock 
    // 这边需要MRC环境
    // 访问了auto变量
    int a = 10; // -->栈区
    void (^block)(void) = ^(void){
        NSLog(@"访问了auto变量 %d",a);
    }
    NSLog(@"%@",block);
    
    // -| NSMallocBlock 
    // ARC环境Xcode帮我们处理成了堆block 
    // 防止出现释放了还去访问导致野指针crash
    int a = 10; // -->栈区
    void (^block)(void) = ^(void){
        NSLog(@"ARC环境 访问了auto变量 %d",a);
    }
    NSLog(@"%@",block);
    
    总结:
    Block类型 环境 内存 拷贝
    NSGlobalBlock 没有访问auto变量 数据区 什么也不做
    NSStackBlock 访问auto变量 从栈复制到堆
    NSMallocBlock NSStackBlock调用了copy 引用计数增加

    在ARC环境下,编译器会自动将栈上的block copy到堆上

    block的使用——链式编程

    block当作函数的返回值
    - (void)viewDidLoad 
    {
        self.getSomeString(@"后被处理");
    }
    - (void(^)(NSString *))getSomeString
    {
        void(^block)(NSString *) = ^(NSString *sting){
            NSLog(@"这边进行一系列处理 %@",sting);
        };
        NSLog(@"这边会被先调用");
        return block;
    }
    
    block当作函数的参数

    异步性:比如AFN的successBlock和failBlock

    - (void)viewDidLoad 
    {
        [self request:^(NSString *string) {
            NSLog(@"%@",string);
        }];
    }
    - (void)request:(void(^)(NSString* string))block
    {
        block(@"异步处理一些问题");
    }
    
    block当作一个参数

    灵活性:保存一段代码块,在任何想用的地方去调用实现

    block的变量截获
    1、局部变量截获,是值的截获
    int num = 10;
    void(^block)(void) = ^(void){
        NSLog(@"num = %d",num);
    };
    num = 20;
    block();
    

    这里num的打印值为10,原因就是对局部变量的截获是值截获。

    NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1",@"2",nil];
    void(^block)(void) = ^(void){
        NSLog(@"%@",arr);
        [arr addObject:@"4"];
    };
    [arr addObject:@"3"];
    arr = nil;
    block();
    

    这里的打印为1,2,3,局部对象变量的截获也是一样,是截获的值,而不是指针,在外部将其置nil也对block没有影响,但是对象调用方法会影响

    2、局部静态变量截获,是指针截获
    static int num = 10;
    void(^block)(void) = ^(void){
        NSLog(@"num = %d",num);
    };
    num = 20;
    block();
    

    这里num的打印值为20,意味着num = 20修改有效的,即是指针截获,同样,在block里去修改变量num也是有效的。

    3、全局变量,静态全局变量block是不截获的,直接进行访问

    具体的可以通过通过命令clang -rewrite-objc xxx.m生成.cpp文件,或者通过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-9.0.0 XX.m.m文件转成 .cpp文件,查看c++的代码。

    相关文章

      网友评论

          本文标题:Block基础

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