Swift3.0 -- 闭包的循环引用与OC的对比

20 篇文章 0 订阅

import UIKit

class ViewController: UIViewController {

    var a: (() -> ())?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //block 中如果出现 self. 要特别小心!
        // "循环"引用,单方向的引用是不会产生循环引用的
        // - 只是闭包对self 进行了copy
        // - 同时需要self对闭包引用
        
        //*******解除循环引用
        // 方法一:用oc的方法
        // 细节1:用var不用let,weak只能修饰var 不能 修饰 let
        // 'weak' must be a mutable variable, because it may change at runtime
        // weak可能会在运行时被修改 -> 指向的对象一旦被释放,会自动设置为nil
//        weak var weakSelf = self;
//        loadData {
            // 细节2
            // 解包有两种方式
            // ? 可选解包  如果self已经被释放,不会向对象发送 view 的消息,更安全
            // ! 强行解包  如果self已经被释放,强行解包会导致崩溃
            // Expression implicitly coerced from 'UIView?' to Any
            
            /*
                weakSelf?.view 只是单纯的发送消息,不参与计算
                强行解包,因为需要计算,可选项不能直接参与计算
            */
//            print(weakSelf?.view);
//        }
        
        
        //方法2 - swift的推荐方法
        //[weak self] 表示 () 中的所有 self 都为弱引用
//        loadData { [weak self] in
//            print(self?.view as Any);
//        }
        
        // 方法3 - swift的另一种方法,知道就好,不安全
        // [unowned self] 表示 () 中的所有 self 都为assign, 不会强引用,如果对象释放,指针地址依然存在
        // 如果对象释放, 会出现野指针的现象
        loadData { [unowned self] in
            print(self.view);
        }
    }
    
    func loadData(bibao: @escaping () -> ()) {
        // 使用属性记录闭包 -> self 对闭包引用
        a = bibao;
        
        //异步
        DispatchQueue.global().async { 
            print("1111");
            
            Thread.sleep(forTimeInterval: 2);
            
            DispatchQueue.main.async(execute: { 
                print("2222");
                bibao();
            })
        }
        
    }
    
    deinit {
        print("qqqqq");
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}


与OC的对比


#import "DemoViewController.h"

@interface DemoViewController ()
@property (nonatomic, copy) void (^blockCallBack)();
@end

@implementation DemoViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
//    //解除方法1:-- __weak
//    __weak typeof(self) weakSelf = self;
//    [self loadData:^{
//        NSLog(@"%@", weakSelf.view);
//    }];
    
    //解除方法2:-- __unsafe_unretained
    //EXC_BAD_ACCESS ,坏内存访问,野指针访问
    // __unsafe_unretained 同样是assign的引用(MRC中并未有weak)
    // MRC中,弱引用直接用assign,不会增加引用计数,但是对象一旦被释放,会出现野指针
    // ARC中,__weak相当于一个观察者,一旦发现对象被释放,会自动设置为nil,会更加安全。
    
    //weak的效率会差一些
    __unsafe_unretained typeof(self) weakSelf = self;
    [self loadData:^{
        NSLog(@"%@", weakSelf.view);
    }];
}

-(void)loadData:(void (^)())block {
    
    self.blockCallBack = block;
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        NSLog(@"延时操作:%@", [NSThread currentThread]);
        
        [NSThread sleepForTimeInterval:2.0];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            
            block();
            
        });
        
    });
    
}

@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值