第 10 條:在既有類中使用關(guān)聯(lián)對象存放自定義數(shù)據(jù)

在某個對象中存放相關(guān)信息。

  • 管理關(guān)聯(lián)對象

關(guān)聯(lián)對象對應(yīng)的屬性分別為:

關(guān)聯(lián)對象 等效的@property屬性
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic, retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic, copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy

管理關(guān)聯(lián)對象的方法有下面三個:

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) //給某對象設(shè)置關(guān)聯(lián)對象值

id objc_getAssociatedObject(id object, const void *key) //根據(jù)給定的鍵,從某對象獲取相應(yīng)的關(guān)聯(lián)對象值
?
void objc_removeAssociatedObjects(id object) //移除某對象的關(guān)聯(lián)對象
  • 用法舉例

展示警告信息時,常用到 UIAlertView , 當(dāng)用戶按下按鈕關(guān)閉該視圖時,需要用到委托(UIAlertViewDelegate)來處理該動作。常用寫法如下:

- (void)askQuestion

{
   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Question"
                                                   message:@"What do you want to do?"
                                                   delegate:self
                                         cancelButtonTitle:@"Cancel"
                                         otherButtonTitles:@"Continue", nil];
  alert.tag = 100;
   [alert show];
}
?
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
   if (buttonIndex == 100) {
  //do something ...
   } else {
       //do something else ...
   }
}

由于代碼分作兩段,讀起來有些亂。

可通過關(guān)聯(lián)對象,在創(chuàng)建創(chuàng)建警告視圖時直接把每個按鈕的邏輯寫好。
即創(chuàng)建完警告視圖后,定義一個代碼塊block,然后在執(zhí)行delegate方法時再將其讀出。示例代碼如下:

#import <objc/runtime.h>
?
static void *EOCMyAlertViewKey = @"EOCMyAlertViewKey";
?
- (void)askQuestion
{
   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Question"
                                                   message:@"What do you want to do?"
                                                   delegate:self
                                         cancelButtonTitle:@"Cancel"
                                         otherButtonTitles:@"Continue", nil];
   
  //按鈕的邏輯緊鄰視圖,更加易讀
   void (^block)(NSInteger) = ^(NSInteger buttonIndex){
       if (buttonIndex == 0) {
           //do something ...
       } else {
           //do something else ...
       }
   };
   
  //給alert對象添加關(guān)聯(lián)對象EOCMyAlertViewKey
   objc_setAssociatedObject(alert, EOCMyAlertViewKey, block, OBJC_ASSOCIATION_COPY);
   [alert show];
}
?
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{   
   void (^block)(NSInteger) = objc_getAssociatedObject(alertView, EOCMyAlertViewKey);
   block(buttonIndex); //調(diào)用block
}

注意:代碼塊block可能要捕獲(capture)某些變量,可能會造成“保留環(huán)(retain cycle)(引用循環(huán)??)”。因此,這種做法雖然很有用,但只應(yīng)該在其他方法行不通的時候采取考慮它。

此外,創(chuàng)建這種 UIAlertView 還有個方法,就是從中繼承子類,把block保存為子類的屬性。

主要來源:《Effective Objective-C 2.0》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容