AssociatedObject封裝AlertView

UIAlertController/UIAlertView

自從iOS8之后蘋果推出了UIAlertController代替UIAlertView贱除,慢慢的UIAlertView也逐漸“失了寵”被deprecated了塘揣。當(dāng)然在使用的過程中我們也發(fā)現(xiàn)了UIAlertController的優(yōu)勢屠阻,自由度更高炕贵,封裝起來更方便于置,至少不用再像UIAlertView那樣設(shè)置代理穿香,實現(xiàn)代理方法那么繁瑣了亭引,所有的操作都可以添加UIAlertAction通過block來進(jìn)行操作。但是有的比較老的項目還要適配iOS7(當(dāng)然這種情況是越來越少了)皮获,UIAlertController在iOS8之前的版本里邊就不能用了焙蚓,然后我就想能不能封裝一個工具類,在iOS8以前的系統(tǒng)里邊使用UIAlertView魔市,之后的使用UIAlertController主届。一直覺得iOS中恰當(dāng)?shù)氖褂胋lock是一件非常優(yōu)雅的事情,當(dāng)然要注意循環(huán)引用的問題待德,所以就想用block來進(jìn)行封裝君丁,代替代理那一套繁瑣的東西。

AlertTool

之前在學(xué)習(xí)runtime相關(guān)知識的時候将宪,看到關(guān)聯(lián)對象這個知識點绘闷,可以完美的解決這個問題橡庞。創(chuàng)建一個UIAlertView的分類
上代碼:

#import <UIKit/UIKit.h>

typedef void (^alertBlock)(NSInteger selectedIndex);

@interface UIAlertView (Category)<UIAlertViewDelegate>

- (void)showAlertView:(alertBlock)block;

@end

然后用associateObject把alertBlock與UIAlertView關(guān)聯(lián)起來

- (void)showAlertView:(alertBlock)block{
    if (block) {
        objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        self.delegate = self;
    }
    [self show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    alertBlock block = objc_getAssociatedObject(self, &alertKey);
    if (block) {
        block(buttonIndex);
    }
}

然后封裝出來一個工具類alertTool

+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message confirmBlock:(void (^)())confirmBlock cancelBlock:(void (^)())cancelBlock{
    NSString *version = [UIDevice currentDevice].systemVersion;
    NSString *alertTitle = !title ? title : @"提示";
    NSString *alertMess = !message ? message : @"提示信息";
    if (version.floatValue >= 8.0) {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:alertTitle message:alertMess preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            confirmBlock();
        }];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            cancelBlock();
        }];
        [alertController addAction:cancelAction];
        [alertController addAction:confirmAction];
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
    }else{
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle message:alertMess delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
        [alertView showAlertView:^(NSInteger selectedIndex) {
            if (selectedIndex == 1) {
                confirmBlock();
            }else{
                cancelBlock();
            }
        }];
        
    }
}

以為這里是一個類方法,所以也不用考慮循環(huán)引用的問題AlertTool Demo印蔗。其實看到這里就會發(fā)現(xiàn)真正的主角是objc_setAssociatedObject/objc_getAssociatedObject

objc_setAssociatedObject/objc_getAssociatedObject

上邊兩個函數(shù)的使用需要導(dǎo)入<objc/runtime.h>扒最,網(wǎng)上關(guān)于關(guān)聯(lián)對象的文章很多,也分析的很透徹华嘹。而且發(fā)現(xiàn)很多優(yōu)秀的三方庫中都有用到這個方法吧趣,我就結(jié)合自己的理解總結(jié)一下,以便以后學(xué)習(xí)耙厚、使用强挫。
就從一個常見的面試題開始 --- 可以在分類中給對象添加屬性嗎?雖然在分類中聲明的屬性在別的類中也能通過點語法獲取到薛躬,但是會warning沒有實現(xiàn)setter/getter方法俯渤,運行的時候也會crash。其實嚴(yán)格意義上來講是不可以的型宝,關(guān)聯(lián)對象卻可以在某種角度來幫我們“實現(xiàn)”這個功能八匠。主要有三個方法:

  • void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy) 此方法用于通過使用給定的鍵和策略為某對象設(shè)置關(guān)聯(lián)對象值,傳入 nil 則可以移除已有的關(guān)聯(lián)對象
  • id objc_getAssociatedObject(id object, void *key)此方法用于通過使用給定的鍵獲取關(guān)聯(lián)對象值
  • void objc_removeAssociatedObjects(id object)移除指定對象所有關(guān)聯(lián)對象趴酣,不常用

使用過程中梨树,如果想要兩個鍵匹配同一個值,則二者必須是完全相同的指針岖寞,即set和get中兩個key必須完全相同劝萤,所以一般會使用靜態(tài)全局變量作為鍵。在分類中添加屬性時慎璧,還可以使用“屬性”getter方法名做key,這樣省得去定義變量跨释。

- (NSString *)propertyName {
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setAssociatedObject_assign:(NSString *)associatedObject_assign {
    objc_setAssociatedObject(self, @selector(propertyName), associatedObject_assign, OBJC_ASSOCIATION_ASSIGN);
}

其實到這里就可以調(diào)用對象點語法去獲取設(shè)置屬性值和獲取屬性值了胸私,但其實這跟我們平時在類中定義的屬性是有區(qū)別的。我們在類中聲明的屬性系統(tǒng)會幫我們生成下劃線開頭的同名的成員變量鳖谈,實現(xiàn)setter/getter方法岁疼。分類中我們雖然手動實現(xiàn)了setter/getter方法,但是沒有并沒有生成成員變量缆娃,你在setter方法中也無法訪問到該成員變量捷绒,具體驗證可以看iOS分類不能添加屬性原因的探索

總的來說贯要,在分類里使用@property聲明屬性暖侨,只是將該屬性添加到該類的屬性列表,并聲明了setter和getter方法崇渗,但是沒有生成相應(yīng)的成員變量字逗,也沒有實現(xiàn)setter和getter方法京郑。但我們手動實現(xiàn)了setter和getter方法也就可以在別的類中通過點語法給該屬性賦值和取值,但是依然沒有相應(yīng)的成員變量葫掉,當(dāng)然你可以自己生成一個成員變量些举,這也是前邊“實現(xiàn)”要加引號的原因。

關(guān)聯(lián)對象還可以用來傳值俭厚,某些場景下可以免去一些繁瑣的步驟户魏,挺好用的工具。其實覺得得runtime里邊的東西越來越有趣挪挤,我也會繼續(xù)研究下去叼丑。理解的比較粗淺,有錯誤的地方歡迎大家指正电禀。

參考:http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle/
http://www.reibang.com/p/79479a09a8c0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幢码,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子尖飞,更是在濱河造成了極大的恐慌症副,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件政基,死亡現(xiàn)場離奇詭異贞铣,居然都是意外死亡,警方通過查閱死者的電腦和手機沮明,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門辕坝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荐健,你說我怎么就攤上這事酱畅。” “怎么了江场?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵纺酸,是天一觀的道長。 經(jīng)常有香客問我址否,道長餐蔬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任佑附,我火速辦了婚禮樊诺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘音同。我一直安慰自己词爬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布权均。 她就那樣靜靜地躺著缸夹,像睡著了一般痪寻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虽惭,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天橡类,我揣著相機與錄音,去河邊找鬼芽唇。 笑死顾画,一個胖子當(dāng)著我的面吹牛击困,可吹牛的內(nèi)容都是我干的祈争。 我是一名探鬼主播一疯,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼琳要,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了慌随?” 一聲冷哼從身側(cè)響起唬血,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤堕阔,失蹤者是張志新(化名)和其女友劉穎咆课,沒想到半個月后末誓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡书蚪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年喇澡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殊校。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡晴玖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出为流,到底是詐尸還是另有隱情呕屎,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布敬察,位于F島的核電站榨惰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏静汤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一居凶、第九天 我趴在偏房一處隱蔽的房頂上張望虫给。 院中可真熱鬧,春花似錦侠碧、人聲如沸抹估。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽药蜻。三九已至瓷式,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間语泽,已是汗流浹背贸典。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留踱卵,地道東北人廊驼。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像惋砂,于是被迫代替她去往敵國和親妒挎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容