Object-C 中 的重要类型

时间:2022-07-10 17:00:45

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;}@endNSString *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]);    }}输出:SteveJobs第二种:- (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);}