本文csdn地址:http://blog.csdn.net/game3108/article/details/51147941
由于Objective-C的動態(tài)語言特性,可以動態(tài)的創(chuàng)建類,添加屬性和方法。
Class demoClass = objc_allocateClassPair([NSObject class], "TestDemo", 0);
class_addMethod(demoClass, @selector(intro), (IMP)&selfIntro, "v@:");
class_addIvar(demoClass,"myVar", sizeof(id), 0, "@");
objc_registerClassPair(demoClass);
其中就有一個class_addIvar可以動態(tài)添加變量。但class_addIvar只能在動態(tài)創(chuàng)建類的時候增加變量,定義類是靜態(tài)創(chuàng)建的類則無法添加。
而Category只能添加方法,使用 @property 也是只會生成setter和getter方法的聲明。具體原因請參考這篇文章,這文章詳細(xì)解釋了Category的實(shí)現(xiàn),為什么可以動態(tài)添加方法,和不能添加實(shí)例變量的原因,這里也不多介紹了。
那如果確實(shí)想給Category增加一個@property的變量,應(yīng)該如何去實(shí)現(xiàn)?
比如如下頭文件:
//
// UIView+Associate.h
// TouchPalDialer
//
// Created by game3108 on 16/3/30.
//
//
#import <UIKit/UIKit.h>
@interface UIView (Associate)
@property (nonatomic, assign) NSInteger associateLength;
@end
首先,先要了解
@property的本質(zhì)其實(shí)是 ivar(實(shí)例變量)+getter+setter
那既然如此,重寫getter和setter方法,并且增加一個ivar的變量,就可以實(shí)現(xiàn)@property的功能
對于重寫getter和setter方法,可以用如下方式
//
// UIView+Associate.m
// TouchPalDialer
//
// Created by game3108 on 16/3/30.
//
//
#import "UIView+Associate.h"
@implementation UIView (Associate)
@dynamic associateLength;
- (NSInteger) associateLength{
NSLog(@"associate get");
return 0;
}
- (void) setAssociateLength:(NSInteger)associateLength{
NSLog(@"associate length : %d" , associateLength);
}
@end
但重寫getter和setter方法還是不夠,必須要創(chuàng)建一個實(shí)例變量,這樣,就用到了OC runtime動態(tài)綁定變量的方法:
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
這樣可以動態(tài)創(chuàng)建一個ivar的實(shí)例變量使用,如下:
//
// UIView+Associate.m
// TouchPalDialer
//
// Created by game3108 on 16/3/30.
//
//
#import "UIView+Associate.h"
#import <objc/runtime.h>
@implementation UIView (Associate)
@dynamic associateLength;
static char associateLengthKey;
- (NSInteger) associateLength{
return [(NSNumber *)objc_getAssociatedObject(self, &associateLengthKey) integerValue];
}
- (void) setAssociateLength:(NSInteger)associateLength{
objc_setAssociatedObject(self, &associateLengthKey, @(associateLength), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
測試代碼
UIView *testView = [[UIView alloc]init];
NSLog(@"test number: %d", testView.associateLength);
testView.associateLength = 20;
NSLog(@"test number: %d", testView.associateLength);
輸出結(jié)果
test number: 0 test number: 20
參考鏈接
1.刨根問底Objective-C Runtime(3)- 消息 和 Category
2.Runtime-動態(tài)創(chuàng)建類添加屬性和方法
3.stackoverflow:objective-c-add-property-in-runtime