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