什么是位段掘譬?
位段(bit-field)是以位為單位來定義結(jié)構(gòu)體(或聯(lián)合體)中的成員變量所占的空間泰演。含有位段的結(jié)構(gòu)體稱為位段結(jié)構(gòu)。
優(yōu)點:采用位段結(jié)構(gòu)既能夠節(jié)省空間葱轩,又方便于操作睦焕。
拓展鏈接:什么是位段?
分析
在實現(xiàn)委托模式時靴拱,如果協(xié)議中的方法是可選的垃喊,經(jīng)常需要寫代碼來判斷某個委托對象是否能響應(yīng)特定的選擇子,那么就會出現(xiàn)下列代碼:
if ([_delegate respondsToSelector:@selector(personDidSomething:)]) {
[_delegate personDidSomething:something];
}
但是在委托對象本身沒變的情況下缭嫡,如果頻繁執(zhí)行此操作的話缔御,那么除了第一次檢測結(jié)果是有用之外,后續(xù)的檢測可能都是多余的妇蛀。在這里耕突,可以把委托對象是否能響應(yīng)某個協(xié)議方法這一信息緩存起來,以優(yōu)化代碼執(zhí)行的效率评架。
案例
@class Man;
@protocol ManDelegate
@optional
- (void)man:(Man)man playGame:(NSString *) game;
- (void)man:(Man)man eatFood:(NSString *)food;
@end
我們可以使用結(jié)構(gòu)體來存儲某個代理是否用respondsToSelector方法檢測過眷茁。先在Man類下聲明一個結(jié)構(gòu)體:
@interface Man () {
struct {
unsigned int playGame : 1;
}_delegateFlags;
}
在上述結(jié)構(gòu)體中,playGame位段占用1個二進(jìn)制位纵诞,它可以表示0或1這兩個值上祈。我們可以通過下面的方法操作上述兩個位段。
//set
_delegateFlags.playGame = 1;
//get
if (?!_delegateFlags.playGame) {}
實現(xiàn)緩存功能所用的代碼可以寫在delegate屬性所對應(yīng)的設(shè)置方法里:
- (void)setDelegate:(id<ManDelegate>)delegate {
_delegate = delegate;
_delegateFlags.playGame = [delegate respondsToSelector:@selector(man:playGame:)];
}
這樣的話浙芙,每次調(diào)用delegate的相關(guān)方法之前登刺,就不用檢測委托對象是否能響應(yīng)給定的選擇子了,而是直接查詢結(jié)構(gòu)體里的標(biāo)識嗡呼。
優(yōu)化前
if ([_delegate respondsToSelector:@selector(man:playGame:)]) {
[_delegate man:self playGame:game];
}
優(yōu)化后
if (_delegateFlags.playGame) {
[_delegate man:self playGame:game];
}
在相關(guān)代理方法需要調(diào)用多次時纸俭,這種緩存優(yōu)化策略還是很有必要的。