欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

iOS Block与循环引用

程序员文章站 2024-02-29 22:22:40
...

循环引用的产生:
下面以ARC 下为例
忧郁Block对象内部引用了外部的变量,而外部的变量又引用了当前的这个block,形成了彼此持有对方。如果外界不主动打断这种链接,那么就会一直持有,导致当前变量对象无法释放。
解决循环引用
1.使用__weak修饰

- (void)test {
    __weak Person *weakPerson = self;
    self.pblock = ^{
        NSLog(@"------%d", weakPerson.age);
    };
}

上述代码因为采用了__weak修饰,导致了Block对象内部以weak形式持有Person示例,用clang编译成cpp文件,查看如下

//xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-9.0.0 Person.m
struct __Person__test_block_impl_0 {
  struct __block_impl impl;
  struct __Person__test_block_desc_0* Desc;
  Person *__weak weakPerson; //weak指针
  __Person__test_block_impl_0(void *fp, struct __Person__test_block_desc_0 *desc, Person *__weak _weakPerson, int flags=0) : weakPerson(_weakPerson) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

2.____unsafe_unretained修饰变量
也可以实现接触循环引用的问题,但是不常用,主要原因是因为____unsafe_unretained指向的对象销毁时,不会自动让这个指针指向的地址值不变,这样导致不安全,__weak指向的对象不存在,则会自动置为nil

- (void)test {
    __unsafe_unretained Person *weakPerson = self;
    self.pblock = ^{
        NSLog(@"------%d", weakPerson.age);
    };
}

3.__block解决循环引用问题
在block内部对当前 对象进行置nil,同时必要调用一次block()。
因为block内部使用__block修饰的当前对象,此时,block引用__block修饰的block对象成员,而此__block对象内部引用当前对象,此时三者形成互相持有关系。
当调用block()后,__block对象内部持有的指向当前对象的指针置nill,此时也就解除了批次的循环指针指向.
iOS Block与循环引用
ARC下最好的实现,就是用__weak,当然如果在MRC下,也可以使用__block解决,因为MRC下__block对象不会对当前的变量进行retain操作

相关标签: block