- Block 與 Method 最大的區(qū)別在于,Block 能夠捕獲上下文中的變量测秸;
- Block 能夠捕獲上下文中的變量是有代價的滨巴,而這個代價就是:
- Block 本質上是對象,alloc release 會有額外開銷骑丸;
- Block 在使用中舌仍,堆 Block 容易引起循環(huán)引用問題;棧 Block 容易引起 SIGSEGV通危;
因為堆 Block 容易引起循環(huán)引用問題铸豁,所以 UIKit 中使用的是 Action 模式、Delegate 模式等菊碟。
因為棧 Block 在非主線程中节芥,容易遇到 SIGSEGV 問題,所以常規(guī)方法 封裝方法
結論
- 在 ViewController - View 層面的接口設計中逆害,應該避免使用 Block头镊,而使用 Action 模式、Delegate 模式等常規(guī) Callback 手段忍燥;
- 在 ViewModel - ViewController 層面的接口設計中拧晕,分為兩種情況:
- ViewModel 是單例,接口需要捕獲上下文中的變量梅垄。這種情況應該使用 Block厂捞, 簡化開發(fā),提高可維護性队丝;
- ViewModel 不是單例靡馁,那么與 ViewController - View 的情況是類似的。無論是 ViewController 持有 ViewModel机久,還是 ViewModel 持有 ViewController臭墨,都容易引起循環(huán)引用問題,極大的增加開發(fā)難度膘盖。這種情況不應該使用 Block胧弛。
結論
今天又有了新的收獲
- 如非必要,盡可能少的使用 Block
- 在 Block 中訪問 self 的實例變量侠畔,必須顯式聲明结缚,避免編譯器語法糖導致的循環(huán)應用。
Block 中訪問實例變量软棺,不顯式聲明 weakSelf->红竭,會引起循環(huán)引用
preferred:
^(NSString *title, NSString *url) {
NSLog(@"%@", weakSelf->testString)
};
not preferred:
^(NSString *title, NSString *url) {
NSLog(@"%@", testString)
};
使用 EXTScope,如果不顯示聲明 self->,也會引起循環(huán)引用
preferred:
@weakify(self)
^(NSString *title, NSString *url) {
@strongify(self);
NSLog(@"%@", self->testString)
};
not preferred:
@weakify(self)
^(NSString *title, NSString *url) {
@strongify(self);
NSLog(@"%@", testString)
};