iOS-底层原理(11)-block-循环引用详解

循环引用问题
iOS-底层原理(11)-block-循环引用详解_第1张图片
image.png

循环引用代码例子如下

#import 

typedef void(^CSBlock)(void);
@interface Person : NSObject
/** age*/
@property(nonatomic,assign)int age;
/** blokc*/
@property(nonatomic,copy) CSBlock block;
@end

@implementation Person
- (void)dealloc {
    NSLog(@"%s",__func__);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        person.age = 100;
        person.block = ^{
            NSLog(@"age = %d",person.age);
        };
    }
    NSLog(@"end");
    return 0;
}

运行结果如下

image.png
解决循环引用问题 - ARC
  • 用__weak、__unsafe_unretained解决
    • __weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil
    • __unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
iOS-底层原理(11)-block-循环引用详解_第2张图片
image.png

代码佐证

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // __weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil
        // __unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
        
        Person *person = [[Person alloc] init];
        person.age = 100;
//        __weak typeof(person) weakPerson = person;
        __unsafe_unretained typeof(person) weakPerson = person;
        person.block = ^{
            NSLog(@"age = %d",weakPerson.age);
        };
    }
    NSLog(@"end");
    return 0;
}
  • 用__block解决(必须要调用block)
iOS-底层原理(11)-block-循环引用详解_第3张图片
image.png

代码佐证

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       // 法三 __block
        __block Person *person = [[Person alloc] init];
        person.age = 10;
        person.block = ^{
            NSLog(@"age is %d", person.age);
            person = nil;
        };
        person.block();
    }
    NSLog(@"end");
    return 0;
}

运行结果

iOS-底层原理(11)-block-循环引用详解_第4张图片
__block.png
解决循环引用问题 - MRC
  • 用__unsafe_unretained解决(MRC环境下不支持__weak)
iOS-底层原理(11)-block-循环引用详解_第5张图片
image.png
  • 用__block解决
iOS-底层原理(11)-block-循环引用详解_第6张图片
image.png

代码例子佐证

int main(int argc, const char * argv[]) {
    @autoreleasepool {
         // MRC环境下
        // MRC不支持__weak的
        __block Person *person = [[Person alloc] init];
        person.age = 10;
        person.block = ^{
            NSLog(@"age is %d", person.age);
        };
        [person release];
    }
    NSLog(@"end");
    return 0;
}

运行结果如下

image.png

面试题 - Block

block的原理是怎样的?本质是什么?

封装了函数调用以及调用环境的OC对象

__block的作用是什么?有什么使用注意点?
  • _block可以用于解决block内部无法修改auto变量值的问题
  • __block不能修饰全局变量、静态变量(static)
  • 编译器会将__block变量包装成一个对象

注意:循环引用问题

详情请看iOS-block底层原理详解之__block属性

block的属性修饰词为什么是copy?使用block有哪些使用注意?
  • block一旦没有进行copy操作,就不会在堆上
  • 使用注意:循环引用问题
block在修改NSMutableArray,需不需要添加__block?
  • 不需要

本文参考借鉴MJ的教程视频,非常感谢.


项目演示代码
iOS-block-cycle


更多block相关文章

iOS-block底层原理详解-本质,类型,copy属性

iOS-copy底层原理之auto变量

iOS-block底层原理详解之__block属性

你可能感兴趣的:(iOS-底层原理(11)-block-循环引用详解)