Swift3.0 -- 閉包的迴圈引用與OC的對比
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
相關文章
- Swift與OC真正去理解Block解決迴圈引用的技巧SwiftBloC
- 迴圈中的非同步&&迴圈中的閉包非同步
- 如何在 Swift 中優雅的處理閉包導致的迴圈引用Swift
- [譯]JS閉包:For迴圈中的setTimeoutJS
- 迴圈引用
- Python迴圈引用是什麼?如何避免迴圈引用?Python
- iOS迴圈引用iOS
- FastJson中迴圈引用的問題ASTJSON
- iOS 關於NSTimer的迴圈引用iOS
- Golang閉包案例分析與普通函式對比Golang函式
- JS 事件迴圈,閉包,作用域鏈題JS事件
- 迴圈輸出——閉包、變數作用域變數
- 解決迴圈引用
- 陣列常見的遍歷迴圈方法、陣列的迴圈遍歷的效率對比陣列
- js陣列迴圈方法對比JS陣列
- require()迴圈引用問題UI
- Block迴圈引用的三種解決方式BloC
- NSTimer迴圈引用的幾種解決方案
- JavaScript 深複製的迴圈引用問題JavaScript
- 怎麼解決引用計數 GC 的迴圈引用問題?GC
- Spring的3級快取和迴圈引用的理解Spring快取
- Go 關閉chanel & chanel的range迴圈Go
- 對javascript閉包的理解JavaScript
- 對JS閉包的理解JS
- Spring如何解決迴圈引用Spring
- iOS | 用於解決迴圈引用的block timeriOSBloC
- for 迴圈與 while 迴圈While
- ARC下的block導致的迴圈引用問題解析BloC
- 迴圈引用導致的json序列化失敗JSON
- 【FastJSON】解決FastJson中“$ref 迴圈引用”的問題ASTJSON
- [NG] 考古 - HttpInterceptor 迴圈引用錯誤HTTP
- SpringBoot 迴圈引用解決辦法Spring Boot
- iOS開發中使用OC和swift的對比iOSSwift
- 探討兩種迴圈表示方法的區別,while迴圈與for迴圈的小總結While
- 從for迴圈中的定時器說開去,閉包和非同步的一點事兒定時器非同步
- 面試:對javascript的閉包的理解面試JavaScript
- spring原始碼之bean的初始化及迴圈引用Spring原始碼Bean
- pl/sql中三種遊標迴圈效率對比SQL
- 全域性元件實現遞迴樹,避免迴圈引用元件遞迴