一,Block的回顧
1,Block通常會(huì)用在網(wǎng)絡(luò)請(qǐng)求中,請(qǐng)求到數(shù)據(jù)后然后回調(diào),先自定義HttpTool的工具類
實(shí)現(xiàn)下請(qǐng)求數(shù)據(jù)的方法
@implementation HttpTool
-(void)loadData:(void(^)(NSString * json))callBack;
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
callBack(@"222");
});
});
}
@end
2,然后在控制器里創(chuàng)建對(duì)象調(diào)用請(qǐng)求方法,等到請(qǐng)求數(shù)據(jù)后就能再Block里做其他的處理了
@interface ViewController ()
@property(nonatomic,strong) HttpTool * tool;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tool = [HttpTool new];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.tool loadData:^(NSString *json) {
NSLog(@"%@",json);
}];
}
@end
二,用閉包來(lái)重寫上面的邏輯
1,閉包的類型:(參數(shù)列表) -> (返回值列表)
import UIKit
class HttpTool: NSObject {
func loadData(callBack : (json : String)->()) {
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("\(NSThread.currentThread())")
dispatch_sync(dispatch_get_main_queue(), {
print("\(NSThread.currentThread())")
callBack(json: "json")
})
}
}
}
2,在控制器調(diào)用
import UIKit
class ViewController: UIViewController {
var tool : HttpTool = HttpTool()
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
tool.loadData { (json) in
print("\(json)")
}
}
}
三,閉包的循環(huán)引用

40CFA1B3-5340-4795-88BF-14526C407707.png
1,第一個(gè)例子中由于HttpTool并沒(méi)有對(duì)callBack這個(gè)Block產(chǎn)生強(qiáng)引用,所以不會(huì)循環(huán)引用,所以在HttpTool中屬性描述一個(gè)Block,然后強(qiáng)引用callBack,就會(huì)發(fā)生循環(huán)引用了
#import "HttpTool.h"
@interface HttpTool ()
@property(nonatomic,copy) void(^callBack)(NSString * json);
@end
@implementation HttpTool
-(void)loadData:(void(^)(NSString * json))callBack;
{
//強(qiáng)引用
self.callBack = callBack;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
callBack(@"222");
});
});
}
@end
如果不對(duì)循環(huán)引用做處理的話,執(zhí)行結(jié)果是:

18E55EAC-1D2A-4DF2-B159-33CB89DBA6A6.png
只要我們weak self 就可以解決循環(huán)引用了
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
__weak ViewController * weakSelf = self;
[self.tool loadData:^(NSString *json) {
NSLog(@"%@",json);
weakSelf.view.backgroundColor = [UIColor redColor];
}];
}

EFFF6E8F-57D3-47CC-B337-63B17860751F.png
2,同樣要解決閉包的循環(huán)引用讓HttpTool強(qiáng)引用這個(gè)閉包c(diǎn)allBack
import UIKit
class HttpTool: NSObject {
//聲明成可選類型的閉包
var callBack :((json : String)->())?
func loadData(callBack : (json : String)->()) {
//強(qiáng)引用
self.callBack = callBack
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("\(NSThread.currentThread())")
dispatch_sync(dispatch_get_main_queue(), {
print("\(NSThread.currentThread())")
callBack(json: "json")
})
}
}
}
3,swift中解決閉包循環(huán)引用的3種方式
import UIKit
class ViewController: UIViewController {
var tool : HttpTool = HttpTool()
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/*
weak var weakSelf = self
tool.loadData { (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
weakSelf?.view.backgroundColor = UIColor.redColor()
}
*/
tool.loadData {[weak self] (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
self?.view.backgroundColor = UIColor.redColor()
}
/*
//這種寫法一旦self為空,就會(huì)報(bào)錯(cuò)
//unowned相當(dāng)于oc中的__unsafe_unretained,__unsafe_unretained 修飾的弱引用,如果指向的對(duì)象銷毀,那么指針指向之前的內(nèi)存地址,很容易產(chǎn)生壞內(nèi)存訪問(wèn),野指針。僵尸對(duì)象
tool.loadData {[unowned self] (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
self.view.backgroundColor = UIColor.redColor()
}
*/
}
//相當(dāng)于oc中的dealloc方法
deinit{
print("deinit")
}
}
四,尾隨閉包
//普通寫法
tool.loadData ({[weak self] (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
self?.view.backgroundColor = UIColor.redColor()
})
//尾隨閉包一
tool.loadData (){[weak self] (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
self?.view.backgroundColor = UIColor.redColor()
}
//尾隨閉包二,當(dāng)閉包為函數(shù)的最后一個(gè)參數(shù)時(shí),會(huì)自動(dòng)省略()
tool.loadData {[weak self] (json) in
print("\(json)")
//weakSelf?.view : 如果前面的可選類型,沒(méi)有值,后面的所有代碼不會(huì)執(zhí)行
//如果有值,系統(tǒng)會(huì)自動(dòng)將weakSelf進(jìn)行解包,并使用weakSelf
self?.view.backgroundColor = UIColor.redColor()
}