写点什么

Block 在开发中的实践应用

作者:NewBoy
  • 2022 年 7 月 18 日
  • 本文字数:2647 字

    阅读完需:约 9 分钟

Block 中访问局部变量

  • Block中访问局部变量


    int main(int argc, const char * argv[]) {        int testNum = 10;        void(^testNumBlock)() = ^{                NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:10
复制代码


  • 在声明Block之后,调用Block之前对局部变量进行修改,在调用Block时局部变量值是修改之前的旧值


    int main(int argc, const char * argv[]) {        int testNum = 10;        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNum = 20;        testNumBlock();        return 0;    }    打印结果:10
复制代码


  • Block中不可以直接修改局部变量


    int main(int argc, const char * argv[]) {        int testNum = 10;        void(^testNumBlock)() = ^{            testNum = 20; //报错            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }
复制代码

Block 内访问__block 修饰的局部变量

  • 在局部变量前使用下划线下划线block修饰,在声明Block之后、调用Block之前对局部变量进行修改,在调用Block时局部变量值是修改之后的新值


    __block int testNum = 10;        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNum = 20;        testNumBlock();    打印结果:20
复制代码


  • 在局部变量前使用下划线下划线block修饰,在Block中可以直接修改局部变量


    int main(int argc, const char * argv[]) {        __block int testNum = 10;        void(^testNumBlock)() = ^{            testNum = 20;            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:20
复制代码

Block 内访问全局变量

  • Block中可以访问全局变量


    int testNum = 10;    int main(int argc, const char * argv[]) {        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:10
复制代码


  • 在声明Block之后、调用Block之前对全局变量进行修改,在调用Block时全局变量值是修改之后的新值


    int testNum = 10;    int main(int argc, const char * argv[]) {        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNum = 20;        testNumBlock();        return 0;    }    打印结果:20
复制代码


  • Block中可以直接修改全局变量


    int testNum = 10;    int main(int argc, const char * argv[]) {        void(^testNumBlock)() = ^{            testNum = 20;            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:20
复制代码

Block 内访问静态变量

  • Block中可以访问静态变量


    int main(int argc, const char * argv[]) {        static int testNum = 10;        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:10
复制代码


  • 在声明Block之后、调用Block之前对静态变量进行修改,在调用Block时静态变量值是修改之后的新值


    int main(int argc, const char * argv[]) {        static int testNum = 10;        void(^testNumBlock)() = ^{            NSLog(@"%d",testNum);        };        testNum = 20;        testNumBlock();        return 0;    }    打印结果:20
复制代码


  • Block中可以直接修改静态变量


    int main(int argc, const char * argv[]) {        static int testNum = 10;        void(^testNumBlock)() = ^{            testNum = 20;            NSLog(@"%d",testNum);        };        testNumBlock();        return 0;    }    打印结果:20
复制代码

Block 作为参数传递

typedef void(^TestBlock)();NSMutableArray *array;void test(){        int a = 10;    TestBlock blcok = ^{        NSLog(@"%d",a);    };    [array addObject:blcok];    NSLog(@"%@",blcok);}
int main(int argc, const char * argv[]) {
array = [[NSMutableArray alloc]init]; test(); TestBlock blockk = [array lastObject]; blockk(); NSLog(@"%@",blockk); return 0;} 结果:在ARC下:test2[2423:124143] <__NSMallocBlock__: 0x1004037f0>test2[2423:124143] 10test2[2423:124143] <__NSMallocBlock__: 0x1004037f0>在非ARC下:程序崩溃 test2[2449:125851] <__NSStackBlock__: 0x7fff5fbff6f8>
复制代码


1、在非 ARC 下,TestBlock 的isa指向__NSStackBlock__,当函数退出后,相应的堆被销毁,block也就不存在了,在经过copyretain之后,对象的类型从__NSStackBlock__变为了__NSMallocBlock__,在函数结束后依然可以访问,在非 ARC 环境下,copyretainblock后一定要在使用后release,不然会有内存泄露,而且泄露点是在系统级,在 Instruments 里跟不到问题触发点,比较上火。


2、ARC 情况下,系统会将捕获了外部变量的block进行了copy。所以返回类型为__NSMallocBlock__,在函数结束后依然可以访问


如果把blcok中的代码不再访问变量:


TestBlock blcok = ^{        NSLog(@"demo");    };结果:ARC和非ARC得结果一致test2[2484:128052] <__NSGlobalBlock__: 0x100005290>test2[2484:128052] demotest2[2484:128052] <__NSGlobalBlock__: 0x100005290>
复制代码

Block 作为返回值

  • 非 ARC 中


- (testBlcok) myTestBlock {    __block int val = 10;    return ^{        NSLog(@"val = %d", val);    };}结果:Xcode就会提示报错Returning block that lives on the local stack
复制代码


在向外传递block的时候一定也要做到,传给外面一个在堆上的,autorelease的对象。


- (testBlcok) myTestBlock {    __block int val = 10;    return [[^{        NSLog(@"val = %d", val);    } copy] autorelease];}
复制代码


  • ARC 中


- (testBlcok) myTestBlock {    __block int val = 10;    return ^{        NSLog(@"val = %d", val);    };}结果:正常
复制代码


在 ARC 环境下,当block作为参数返回的时候,block也会自动被移到堆上。

Block 作为属性

ARC 和非 ARC 得声明一样


@property (strong, nonatomic) TestBlock *strongBlock;@property (copy, nonatomic) TestBlock *copyBlock;
复制代码




发布于: 刚刚阅读数: 4
用户头像

NewBoy

关注

虽不年少,艳阳高照 2019.04.10 加入

还未添加个人简介

评论

发布
暂无评论
Block在开发中的实践应用_ios_NewBoy_InfoQ写作社区