ios 基础 面试

Block的三种类型:__NSGlobalBlock,__NSS

2018-08-31  本文已影响101人  小心韩国人

我们在讲block的本质的时候已经知道了,block的本质就是一个 OC 对象,那么既然它是一个 OC 对象,它就会有类型,本文就将讲解block的三种类型.
我们在讲block的三种类型之前,先了解一下程序的内存分配情况,因为不同类型的block分配的内存也不同.

一: __NSGlobalBlock
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        static int age = 10;
        void(^block)(void) = ^{
            NSLog(@"Hello, World! %d",age);
        };
        NSLog(@"%@",[block class]);
    }
    return 0;
}
控制台输出:__NSGlobalBlock__

这个很好理解,不过多解释

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int age = 10;
        void(^block)(void) = ^{
            NSLog(@"Hello, World! %d",age);
        };
        NSLog(@"%@",[block class]);
    }
    return 0;
}
控制台输出:__NSMallocBlock__

怎么打印的是__NSMallocBlock__,刚才不是说访问了auto变量就是__NSStackBlock吗?
因为这里我们使用的是ARC,在ARC环境下,Xcode会默认帮我们做很多事情,我们在Build Settings中把ARC设置成MRC,再来打印一下:

2018-08-30 17:37:09.846365+0800 block的类型[4318:3463149] __NSStackBlock__

这次打印的就是__NSStackBlock__
❓我们思考一下,__NSStackBlock在访问外部变量时,会有什么问题?

所以,为了避免出现这种情况,我们需要把block存储在堆上,__NSMallocBlock就闪亮登场了.

❓思考:如果我们对__NSGlobalBlock 进行一次 copy操作,会发生什么变化呢?

__NSGlobalBlock copy后
‼️注意

以上都是在MRC环境下,如果是在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下几种情况:

总结:

上一篇下一篇

猜你喜欢

热点阅读