對比
Delegate(委托/代理)
優(yōu)點:
1.同一個協(xié)議,一個對象只能同時設置一個代理篓冲,單例一般不用代理李破;
2.相對側(cè)重于過程;
3.降低代碼的耦合性壹将,事件監(jiān)聽和處理相對分離嗤攻。
缺點:
1.實現(xiàn)過程繁瑣;
2.跨層傳值監(jiān)聽不方便诽俯;
3.難以對多個對象同時傳值妇菱。Block(塊)
優(yōu)點:
1.書寫簡練;
2.側(cè)重結果;
3.配合GCD解決多線程問題闯团。
缺點:
1.需要防止循環(huán)引用辛臊;
2.delegate運行成本低,block成本很高的。
block出棧需要將使用的數(shù)據(jù)從棧內(nèi)存拷貝到堆內(nèi)存偷俭,當然對象的話就是加計數(shù)浪讳,使用完或者block置nil后才消除;delegate只是保存了一個對象指針涌萤,直接回調(diào)淹遵,沒有額外消耗。相對C的函數(shù)指針负溪,只多做了一個查表動作Notification(通知)
優(yōu)點:
1.一對多透揣,解決了多對象監(jiān)聽問題;
2.傳值方便快捷川抡,Context自身攜帶相應的內(nèi)容辐真。
缺點:
1..使用完要記得注銷通知,防止crash崖堤;
2.調(diào)試的時候動作的跟蹤將很難進行侍咱;
3.需要一個第三方的對象來做監(jiān)聽者與被監(jiān)聽者的中介。
Delegate
//協(xié)議文件中,值提供方法的聲明,不提供具體的實現(xiàn)內(nèi)容
//誰遵循了該協(xié)議,誰來實現(xiàn)協(xié)議中聲明的方法
//協(xié)議本身可以遵循其他協(xié)議
//默認情況下所有的協(xié)議,都遵循了NSObject基礎協(xié)議
@class NAEvaluateCell;
@protocol NAEvaluateCellDelegate <NSObject>
// 可選實現(xiàn)標記
@optional
- (void)addPictures;
// 必選實現(xiàn)標記密幔,語法級別警告,并不會導致程序編譯錯誤
@required
- (void)evaluateCell:(NAEvaluateCell *)cell deleteIndex:(NSInteger)index;
@end
一些注意點:
1 做判斷
if (self.delegate && [self.delegate respondsToSelector:@selector(evaluateCell:deleteIndex:)]) {
[self.delegate evaluateCell:weakSelf deleteIndex:index];
}
2 遵循協(xié)議<NAEvaluateCellDelegate>
3 實現(xiàn)方法
Block
typedef void (^deleteData)(int index);
@interface NAEvaluateItemCell : UICollectionViewCell
/** 宏定義方式 */
@property (nonatomic, copy) deleteData deleteDataIndex;
/** 直接書寫 */
@property (nonatomic, copy) void (^clickBlock)(void); // 無參數(shù)無返回值
@end
// 使用
self.clickBlock();
[cell setClickBlock:^{ }];
if (self.deleteDataIndex) {
self.deleteDataIndex((int)self.indexPath.row);
}
cell.deleteDataIndex = ^(int index) {
};
- Block模式
1.無參數(shù)無返回值
void (^emptyBlock)() = ^(){
NSLog(@"無參數(shù)無返回值");
};
emptyBlock();
2.有參數(shù)無返回值
void (^sumBlock)(int, int) = ^(int a, int b){
NSLog(@"有參數(shù)無返回值");
};
sumBlock(10,10);
3.有參數(shù)有返回值
NSString* (^logBlock)(NSString *, NSString *) = ^(NSString *str1, NSString *str2){
return [NSString stringWithFormat:@"%@%@",str1,str2];
};
NSLog(@"%@", logBlock(@"有參數(shù)有返回值的", @"Block"));
- 循環(huán)引用解決方案
ARC
如果用copy修飾Block,該Block就會存儲在堆空間楔脯。則會對Block的內(nèi)部對象進行強引用,導致循環(huán)引用,內(nèi)存無法釋放
__weak typeof (target)weakTarget = target;
如果用weak修飾Block,該Block就會存放在椏杷Γ空間昧廷。不會出現(xiàn)循環(huán)引用問題
MRC
用copy修飾后要在Block內(nèi)部使用對象,則需要__block typeof (target)blockTarget = target;
- 使用場合偎箫。
任務完成時回調(diào)處理
消息監(jiān)聽回調(diào)處理
錯誤回調(diào)處理
枚舉回調(diào)
視圖動畫木柬、變換
排序
- 主線程中UI操作
dispatch_async(dispatch_get_main_queue(), <^(void)block>)
Notification
- (void)addNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary* info = [notification userInfo];
CGFloat height = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
[UIView animateWithDuration:0.2 animations:^{
} completion:^(BOOL finished) {
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
}
#pragma mark 銷毀時移除
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
根據(jù)isa指針,block一共有3種類型的block
_NSConcreteGlobalBlock 全局靜態(tài)
_NSConcreteStackBlock 保存在棧中淹办,出函數(shù)作用域就銷毀
_NSConcreteMallocBlock 保存在堆中眉枕,retainCount == 0銷毀
重要經(jīng)驗五:block作為屬性的注意事項
iOS中Block的基礎用法
知乎上block問題回答
Block,Delegate,Notification
淺談 iOS Notification
iOS Block底層實現(xiàn)原理詳解
Block全面分析
單例傳值、block傳值怜森、代理傳值與通知中心傳值