温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

block应该注意的三个问题!

发布时间:2020-07-09 15:06:45 来源:网络 阅读:437 作者:禅信23 栏目:移动开发

问题一: block对象的生命周期?

直接看代码,打印结果是什么?

#import <Foundation/Foundation.h>

//定义block对象(全局block)
int (^externBlock)(void) = ^(void){return 100;};
//定义函数(block做为参数)
void function(int (^block)(void)) {
    printf("执行block的结果是:%d\n\n", block());
}
//定义的两个函数
void firstFunc(int number) {
    //定义块对象(局部)
    int (^blockWithinFirst)(void) = ^(void) { return number; };
    //调用外部的function函数
    function(blockWithinFirst);
    //赋值
    externBlock = blockWithinFirst;
}
void secondFunc(int number) {
    //int局部变量
    int index = 10;
    //block局部对象
    int (^blockWithinSecond)(void) = ^(void) {return number * index;};
    //调用外部function函数
    function(blockWithinSecond);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //1.调用function函数
        function(externBlock);
        //2.调用firstFunc
        firstFunc(5);
        //3.调用secondFunc
        secondFunc(10);
        //4.和步骤1一样
        function(externBlock);
    }
    return 0;
}


问题二:Block体中访问全局变量/局部静态变量/局部变量的问题,如何解决(考察__block类型)

#import <Foundation/Foundation.h>
void function(int number, void (^blockParam)(void)) {
    //打印传入的number值
    printf("传入的number是: %d\n", number);
    //调用传入的block对象
    blockParam();
}

int globalNumber = 1000;//全局变量(外部变量)

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        //块声明(没有传参,没有返回值)
        void (^internalBlock)(void);
        //局部静态变量
        static int localStaticInt = 20;
        //局部变量:local variable(自由变量:free variable)
        int localInt = 20;
        
        //第一部分:将block对象最为函数的参数,在函数内部调用block
        //块定义(打印上面三个变量的值);
        internalBlock = ^(void) { printf("全局变量globalNumber:%d; 局部静态变量localStaticInt:%d; 局部变量localInt:%d\n", globalNumber, localStaticInt, localInt); };
        //将internalBlock块对象作为function的参数,调用function函数
        function(1, internalBlock);

        //第二部分:修改上述三个变量的值,重新调用function函数
        globalNumber   = 3000;
        localStaticInt = 0;
        localInt       = 0;
        function(2, internalBlock);

        //第三部分:重新再写一次block的定义部分,再调用function函数
        internalBlock = ^(void) { printf("全局变量globalNumber:%d; 局部静态变量localStaticInt:%d; 局部变量localInt:%d\n", globalNumber, localStaticInt, localInt); };
        function(3, internalBlock);
        
        //第四部分:考察__block类型修饰问题
        __block int localAnotherInt = 20;
        void (^firstBlock)(void) = ^(void) {
            globalNumber += 100;
            localStaticInt += 200;
            localAnotherInt = 10;
            printf("重新赋值后的globalNumber:%d;localStaticInt:%d; localAnotherInt:%d\n\n", globalNumber, localStaticInt,localAnotherInt);
        };
        //调用/执行firstBlock
        firstBlock();
    }
    return 0;
}

分析:

    初始化:全局:1000; 局部静态:20; 局部变量:20

     a. function(1, internalBlock); 包除了包含可执行的代码,还包含可访问的变量的值(全局:1000; 局部静态:20; 局部变量:20)

     b. globalNumber   = 3000;

     localStaticInt = 0;

     localInt       = 0;

     function(2, internalBlock);

     包除了包含可执行的代码,还包含可访问的变量的值(全局:3000; 局部静态:0; 局部变量:20);原因是block体内对局部变量没有修改的权限,还是原来第一次执行的包的数据

     c. 重新再定义internalBlock块对象, 此时包内就重新包含了新的值(全局:1000; 局部静态:0; 局部变量:0)

        internalBlock = ^(void) { printf("全局变量globalNumber:%d; 局部静态变量localStaticInt:%d; 局部变量localInt:%d\n", globalNumber, localStaticInt, localInt); };

    function(3, internalBlock);

    d.如果把局部的变量的类型添加__block类型,可以在block体中修改局部变量的值(重新赋值后的globalNumber:3100;localStaticInt:200; localAnotherInt:10


问题三:Block体循环应用的问题,如何解决(考察__weak类型)

    TRBlockObject *blockObj = [TRBlockObject new];
    blockObj.block = ^void(void){
        NSLog(@"blockObj%@“,blockObj);
    };

例子中,block属性是blockObj对象的;而在block体中,block又引用了blockObj对象,造成了循环引用。

解决的办法是:

    TRBlockObject *blockObj = [TRBlockObject new]; 
    //解决循环引用的方案使用__weak修饰符。
    __weak TRBlockObject *weakBlockObj = blockObj;
    
    blockObj.block = ^void(void){
        NSLog(@"blockObj%@",weakBlockObj);
    };

__weak是弱引用,blockObj被释放的时候,weakBlockObj已经是nil了。


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI