谈谈OC中的循环引用

1.什么时候会发生循环引用

将一个提前准备好的代码块, 在需要执行的时候立即执行, 在不需要立即执行的时候, 用个属性将这个函数传递过来的block记录下来, 产生了强引用, 此时就会发生循环引用

2.怎么解决循环引用

那么怎么解决循环引用, 就是打破任一方的强引用

.

  • 其中使用最多的就是__weak, 声明一个弱引用类型的自己, 解除循环引用, 其中__weak跟weak类似, 当对象被系统回收时, 它的内存地址会自动指向nil, 对nil进行任何操作不会有反应

  • 但其实在ios4的时候, 也可以使用__unsafe_unretained, 解除强引用, 但是它存在一定的不安全性, 原理和assign类似, 当对象被系统回收时, 它的内存地址不会自动指向nil, 就有可能出现坏内存地址的访问, 也就发生野指针错误

  • 在之前发现了很多解除循环引用的时候, 会先使用__weak, 声明自己为弱引用类型, 然后在准备好的代码块中也就是block中, 再对弱引用对象利用__strong 做一次强操作 , 仔细验证发现再做强引用操作是冗余的, 并不会产生影响, 可以不用写

3.如何验证是否发生循环引用

.

4.simple demo

#import "ViewController.h"
#import "NetworkTools.h"


@interface ViewController ()
@property (nonatomic, strong) NetworkTools *tools;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tools = [[NetworkTools alloc] init];
   
/*
    //解决方式三: __unsafe_unretained 不推荐, 不安全
    __unsafe_unretained typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"%@%@",html,strongSelf.view);
        strongSelf.view.backgroundColor = [UIColor redColor];
    }];
*/

    //解决方式二: __weak
    __weak typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"%@%@",html,strongSelf.view);
        strongSelf.view.backgroundColor = [UIColor redColor];
    }];
    
}

//解决方式一: 
- (void) method1{
    NetworkTools *tools = [[NetworkTools alloc] init];
    [tools loadData:^(NSString *html) {
        NSLog(@"%@%@",html,self.view);
        self.view.backgroundColor = [UIColor redColor];
    }];
}

- (void)dealloc {
    NSLog(@"VC dealloc");
}
@end

#import "NetworkTools.h"

@interface NetworkTools ()

//用一个属性 来记录 函数传递过来的 block
@property (nonatomic, copy) void(^finishedBlock)(NSString *);

@end

@implementation NetworkTools

- (void)loadData:(void (^)(NSString *))finishedCallBack {
   
    //开始记录blcok
    self.finishedBlock = finishedCallBack;

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
     
        [NSThread sleepForTimeInterval:3];
      
        //开始耗时任务
        NSLog(@"开始加载数据");
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //调用方法
            [self working];
        });
    }); 
}

- (void) working {
    //执行block
    if (self.finishedBlock) {
        self.finishedBlock(@"<html>");
    }
}

- (void)dealloc {
    NSLog(@"Tools dealloc");
}

@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,902评论 10 69
  • 那个穿蓝色白条纹裤,上身穿黑色T恤,绑个马尾辫在设备部的姑娘,我想认识你呀!哈哈,哈哈,你好漂亮!
    leyes阅读 173评论 0 0
  • 百无聊赖地躺在床上,心情有点烦闷。都重阳了,暑意没有一点儿要消退的意思,蛐蛐叫了一夏,还不知道夏季已过。全球变暖似...
    种花家吴岭阅读 237评论 0 0
  • 啃《西方哲学史》洛克的政治学说一章,看时突然有些模糊地理解,所有这些理论,包括劳动价值说、咱从小学的马克思那一套啥...
    Allul阅读 721评论 0 1
  • 写这篇文章,酝酿了很久。是自己的切身体会,也是对生活的反思。虽然酝酿已久,但并未有很强的逻辑性。算是一篇随笔。 我...
    爱逗子阅读 732评论 4 8