??這里主要是把block和代理作為回調(diào)的兩種方式虾宇,在應(yīng)用場(chǎng)景上進(jìn)行比較旨剥。block和代理本質(zhì)上是不同的,因?yàn)閎lock其實(shí)是一個(gè)對(duì)象臭墨,代理是一種設(shè)計(jì)模式(委托-代理模式)。
1.block簡(jiǎn)介
??在 iOS中膘盖, block一共分三種胧弛。
??(1)全局靜態(tài) block尤误,不會(huì)訪問(wèn)任何外部變量,執(zhí)行完就銷毀结缚。
^{
NSLog(@"Hello World!");
}();
??(2)保存在棧中的 block损晤,當(dāng)函數(shù)返回時(shí)會(huì)被銷毀,和第一種的區(qū)別就是調(diào)用了外部變量红竭。
[UIView animateWithDuration:3 animations:^{
self.view.backgroundColor = [UIColor redColor];
}];
??(3)保存在堆中的 block尤勋,當(dāng)引用計(jì)數(shù)為 0 時(shí)會(huì)被銷毀。例如按鈕的點(diǎn)擊事件茵宪,一直存在最冰,即使執(zhí)行過(guò),也不銷毀眉厨,因?yàn)榘粹o還可能被點(diǎn)擊锌奴。直到持有按鈕的View被銷毀,它才會(huì)被銷毀憾股。
#import <UIKit/UIKit.h>
typedef void(^ButtonClickBlcok)();
@interface TestView : UIView
@property (nonatomic, copy) ButtonClickBlcok buttonClickBlcok;
@end
#import "TestView.h"
@implementation TestView
- (IBAction)buttonClick:(id)sender {
if (self.buttonClickBlcok) {
self.buttonClickBlcok();
}
}
@end
2.代理簡(jiǎn)介
??在為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)鹿蜀。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象服球,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用茴恰。摘自百度百科
??代理是一種通用設(shè)計(jì)模式,很多語(yǔ)言上都有實(shí)現(xiàn)斩熊。在iOS中往枣,代理作為一種消息傳遞方式,使用的非常普遍粉渠。代理包括三部分:代理分冈,委托,協(xié)議霸株。代理方通過(guò)實(shí)現(xiàn)協(xié)議里的方法雕沉,接收委托方傳遞過(guò)來(lái)的消息。
3.block的優(yōu)勢(shì)
??block的代碼可讀性更好去件。因?yàn)閎lock只要實(shí)現(xiàn)就可以了坡椒,而代理需要遵守協(xié)議并且實(shí)現(xiàn)協(xié)議里的方法,而兩者還不在一個(gè)地方尤溜。代理使用起來(lái)也更麻煩倔叼,因?yàn)橐暶鲄f(xié)議、聲明代理屬性宫莱、遵守協(xié)議丈攒、實(shí)現(xiàn)協(xié)議里的方法僚纷。block不需要聲明及志,也不需要遵守缕棵,只需要聲明屬性和實(shí)現(xiàn)就可以了入愧。
??block是一種輕量級(jí)的回調(diào),可以直接訪問(wèn)上下文深碱,由于block的代碼是內(nèi)聯(lián)的,運(yùn)行效率更高藏畅。block就是一個(gè)對(duì)象敷硅,實(shí)現(xiàn)了匿名函數(shù)的功能。所以我們可以把block當(dāng)做一個(gè)成員變量愉阎、屬性绞蹦、參數(shù)使用,使用起來(lái)非常靈活榜旦。像用AFNetworking請(qǐng)求數(shù)據(jù)和GCD實(shí)現(xiàn)多線程幽七,都使用了block回調(diào)。
4.block劣勢(shì)
??blcok的運(yùn)行成本高溅呢。block出棧需要將使用的數(shù)據(jù)從棧內(nèi)存拷貝到堆內(nèi)存澡屡,當(dāng)然對(duì)象的話就是引用計(jì)數(shù)加1,使用完或者block置nil后才銷毀咐旧。delegate只是保存了一個(gè)對(duì)象指針(一定要用week修飾delegate驶鹉,不然也會(huì)循環(huán)引用),直接回調(diào)铣墨,沒(méi)有額外消耗室埋。就像C的函數(shù)指針,只多做了一個(gè)查表動(dòng)作伊约。
??block容易造成循環(huán)引用姚淆,而且不易察覺(jué)。因?yàn)闉榱薭lcok不被系統(tǒng)回收屡律,所以我們都用copy關(guān)鍵字修飾腌逢,實(shí)行強(qiáng)引用。block對(duì)捕獲的變量也都是強(qiáng)引用疹尾,所以就會(huì)造成循環(huán)引用上忍。
#import "ViewController.h"
typedef void(^TestBlock)(void);
@interface ViewController ()
{
void (^_testCycleBlock)(void);
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
__weak ViewController *weakSelf = self;
_testCycleBlock = ^{
/**
//引發(fā)循環(huán)引用
NSLog(@"%@", self);
*/
//防止循環(huán)引用
NSLog(@"%@", weakSelf);
};
}
@end
5.如何使用
??優(yōu)先使用block。
??如果回調(diào)的狀態(tài)很多纳本,多于三個(gè)使用代理窍蓝。
??如果回調(diào)的很頻繁,次數(shù)很多繁成,像UITableview吓笙,每次初始化、滑動(dòng)巾腕、點(diǎn)擊都會(huì)回調(diào)面睛,使用代理絮蒿。
??block和代理都各有優(yōu)缺點(diǎn),所以我們一定要理解區(qū)分使用場(chǎng)景叁鉴,應(yīng)用適合的回調(diào)方式土涝。優(yōu)化APP的性能,提高流暢性幌墓,從點(diǎn)滴做起但壮。