Objective-C運行時定義了幾種重要的類型。
Class
:定義Objective-C類Ivar
:定義對象的實例變量,包括類型和名字。Protocol
:定義正式協議。objc_property_t
:定義屬性。叫這個名字可能是爲了防止和Objective-C 1.0中的用戶類型衝突,那時候還沒有屬性。Method
:定義對象方法或類方法。這個類型提供了方法的名字(就是**選擇器**)、參數數量和類型,以及返回值(這些信息合起來稱爲方法的**簽名**),還有一個指向代碼的函數指針(也就是方法的**實現**)。SEL
:定義選擇器。選擇器是方法名的唯一標識符。-
IMP
:定義方法實現。這只是一個指向某個函數的指針,該函數接受一個對象、一個選擇器和一個可變長參數列表(varargs),返回一個對象
運行時動態添加Category屬性
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface NSObject (CategoryWithProperty)
/**
* 要在Category中擴展的屬性
*/
@property (nonatomic, strong) NSObject *property;
@end
@implementation NSObject (CategoryWithProperty)
- (NSObject *)property {
return objc_getAssociatedObject(self, @selector(property));
}
- (void)setProperty:(NSObject *)value {
objc_setAssociatedObject(self, @selector(property), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
@implementation SomeClass
- (id)init {
self = [super init];
if (self) _privateName = @"Steve";
return self;
}
@end
NSString *nameGetter(id self, SEL _cmd) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
return object_getIvar(self, ivar);
}
void nameSetter(id self, SEL _cmd, NSString *newName) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
id oldName = object_getIvar(self, ivar);
if (oldName != newName) object_setIvar(self, ivar, [newName copy]);
}
int main(void) {
@autoreleasepool {
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C = copy
objc_property_attribute_t backingivar = { "V", "_privateName" };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_addProperty([SomeClass class], "name", attrs, 3);
class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:");
class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "v@:@");
id o = [SomeClass new];
NSLog(@"%@", [o name]);
[o setName:@"Jobs"];
NSLog(@"%@", [o name]);
}
}
輸出:
Steve
Jobs
第二種:
- (id)valueForUndefinedKey:(NSString *)key
第三種:
static char const * const ObjectTagKey;
@implementation NSObject (ExampleCategoryWithProperty)
@dynamic objectTag;
- (id)objectTag {
return objc_getAssociatedObject(self, ObjectTagKey);
}
- (void)setObjectTag:(id)newObjectTag {
objc_setAssociatedObject(self, ObjectTagKey, newObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}