在某個對象中存放相關(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保存為子類的屬性。