swift之block的循环引用

ViewController

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


/*
 接触循环引用   打破引用循环即可
1.不使用成员变量 来调用闭包
2.__weak or __unsafe_unretained
 */
@interface ViewController ()
@property (nonatomic, strong) NetworkTools *tools;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //加载网络数据
    self.tools = [[NetworkTools alloc] init];
    
    //以后工作中 大家会看到大量以下代码
    //不会有任何不同
    //将一个弱引用的对象 在闭包中变成强引用的对象 希望 在对象self在被回收时  记录self  以便能够继续访问方法
    //但是就是个棒槌  没有任何作用
    __unsafe_unretained typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"data = %@",html);
        NSLog(@"%@",strongSelf.view);
    }];
}

- (void) method2 {
    //加载网络数据
    self.tools = [[NetworkTools alloc] init];
    
    //定义block的时候  在block中使用了外部变量 会默认做copy操作
    //会对self进行强引用
    
    
    ////接触循环引用的方法二
    // __weak 相当于 weak关键字修饰 当对象被回收时  对象地址会自动指向nil  给nil发送消息 在OC中是可以的
    //不会造成野指针访问
    //iOS 5.0之后推出的
    __weak typeof(self) weakSelf = self;
    
    //    __unsafe_unretained typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        NSLog(@"data = %@",html);
        //现在会产生循环引用嘛?
        NSLog(@"%@",weakSelf.view);
    }];
}


- (void) method1 {
    //加载网络数据
    self.tools = [[NetworkTools alloc] init];
    
    //定义block的时候  在block中使用了外部变量 会默认做copy操作
    //会对self进行强引用
    
    //    __weak typeof(self) weakSelf = self;
    
    //接触循环引用的方法1
    //__unsafe_unretained 相当于assgin关键字 修饰  当对象被回收是  对象地址不会指向nil
    //iOS 4.0推出的
    //会导致坏地址访问  俗称 野指针
    __unsafe_unretained typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        NSLog(@"data = %@",html);
        //现在会产生循环引用嘛?
        NSLog(@"%@",weakSelf.view);
    }];
}

NetworkTools.h

#import 

@interface NetworkTools : NSObject


//定义网络访问方法
- (void) loadData:(void(^)(NSString *html))finished;
@end

NetworkTools.m

#import "NetworkTools.h"

@interface NetworkTools ()
@property (nonatomic, copy) void (^finishedBlock)(NSString *);

@end

@implementation NetworkTools



//block是一组准备好的代码  在需要的时候执行
//可以当做参数传递
//在异步方法中如果能直接执行block就直接执行
//如果不需要立即执行 就需要用一个属性来 记录block  在需要的时候执行

//finished执行完就解除了对self的强引用


- (void)loadData:(void (^)(NSString *))finished {
    
    //记录block
    self.finishedBlock = finished;
    //异步加载数据
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        
        //睡 3秒
        [NSThread sleepForTimeInterval:3];
        //耗时任务结束后 主线程完成回调
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"回调数据");
//            finished(@"终于拿到数据");
            [self working];
        });
    });
}

- (void) working {
    
    //在调用block的时候需要判断是否为空
    if (self.finishedBlock) {
        self.finishedBlock(@"回调数据");
    }
}


你可能感兴趣的:(Swift教程)