類擴(kuò)展時(shí)Apple又只提供了對(duì)方法的擴(kuò)展,對(duì)屬性的擴(kuò)展是不會(huì)自動(dòng)生成_變量以及屬性的setter:和getter方法寸认。但蘋果提供了runtime,我們可以通過runtime使用關(guān)聯(lián)API就可以做到對(duì)屬性的擴(kuò)展调缨。
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*/
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
/**
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association.
* @param key The key for the association.
*
* @return The value associated with the key \e key for \e object.
*/
id objc_getAssociatedObject(id object, const void *key)
/**
* Removes all associations for a given object.
*
* @param object An object that maintains associated objects.
*
* @note The main purpose of this function is to make it easy to return an object
* to a "pristine state”. You should not use this function for general removal of
* associations from objects, since it also removes associations that other clients
* may have added to the object. Typically you should use \c objc_setAssociatedObject
* with a nil value to clear an association.
*/
void objc_removeAssociatedObjects(id object)
- 設(shè)置關(guān)聯(lián)值
對(duì)于設(shè)置關(guān)聯(lián)丧肴,我們需要使用下面的API關(guān)聯(lián)起來:
/**
object:與誰關(guān)聯(lián),通常是傳self
key:唯一鍵月弛,在獲取值時(shí)通過該鍵獲取肴盏,通常是使用static const void *來聲明
value:關(guān)聯(lián)所設(shè)置的值
policy:內(nèi)存管理策略,比如使用copy
*/
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
- 獲取關(guān)聯(lián)值
如果我們要獲取所關(guān)聯(lián)的值帽衙,需要通過key來獲取菜皂,調(diào)用如下函數(shù):
/**
object:與誰關(guān)聯(lián),通常是傳self厉萝,在設(shè)置關(guān)聯(lián)時(shí)所指定的與哪個(gè)對(duì)象關(guān)聯(lián)的那個(gè)對(duì)象
key:唯一鍵恍飘,在設(shè)置關(guān)聯(lián)時(shí)所指定的鍵
*/
id objc_getAssociatedObject(id object, const void *key)
- 關(guān)聯(lián)策略
我們先看看設(shè)置關(guān)聯(lián)時(shí)所指定的policy,它是一個(gè)枚舉類型谴垫,看官方說明:
/**
* Policies related to associative references.
* These are options to objc_setAssociatedObject()
*/
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
關(guān)聯(lián)類型與等效@property屬性
OBJC_ASSOCIATION_ASSIGN:assign(弱引用關(guān)聯(lián)章母,通常是基本數(shù)據(jù)類型,如int翩剪、float)
OBJC_ASSOCIATION_RETAIN_NONATOMIC:nonatomic,retain(表示強(qiáng)(strong)引用關(guān)聯(lián)對(duì)象)
OBJC_ASSOCIATION_COPY_NONATOMIC:nonatomic,copy(表示關(guān)聯(lián)對(duì)象copy)
OBJC_ASSOCIATION_RETAIN:retain(表示強(qiáng)(strong)引用關(guān)聯(lián)對(duì)象乳怎,但不是線程安全的)
OBJC_ASSOCIATION_COPY:copy(表示關(guān)聯(lián)對(duì)象copy,但不是線程安全的)
例子
UIViewController + viewInfo.h文件
#import <UIKit/UIKit.h>
@interface UIViewController (viewInfo)
@property (nonatomic, copy) NSString *name; //視圖名字
@property (nonatomic, assign) BOOL hasChildViewController; //是否有子視圖
@property (nonatomic, strong) UIImage *backgroundImage; //背景圖片
@end
UIViewController + viewInfo.m文件
#import "UIViewController+viewInfo.h"
#import <objc/runtime.h>
static const void *kName = "name";
static const void *kHasChildViewController = @"hasChildViewController";
static const void *kBackgroundImage = @"backgroundImage";
@implementation UIViewController (Information)
#pragma mark - 字符串類型的動(dòng)態(tài)綁定
- (NSString *)name {
return objc_getAssociatedObject(self, kName);
}
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, kName, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
#pragma mark - BOOL類型的動(dòng)態(tài)綁定
- (BOOL)hasChildViewController {
return [objc_getAssociatedObject(self, kHasChildViewController) boolValue];
}
- (void)setHasChildViewController:(BOOL)hasChildViewController {
objc_setAssociatedObject(self, kHasChildViewController, [NSNumber numberWithBool:hasChildViewController], OBJC_ASSOCIATION_ASSIGN);
}
#pragma mark - 類類型的動(dòng)態(tài)綁定
- (UIImage *)backgroundImage {
return objc_getAssociatedObject(self, kBackgroundImage);
}
- (void)setBackgroundImage:(UIImage *)backgroundImage {
objc_setAssociatedObject(self, kBackgroundImage, backgroundImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end