以动态解析来实现@dynamic属性
+ (BOOL)resolveInstanceMethod:(SEL)sel { NSString *selectorString = NSStringFromSelector(sel); // 获取方法的类型编码(type encoding)做铺垫 Method exchangeSetM = class_getInstanceMethod([self class], @selector(insteadSetMethod)); Method exchangeGetM = class_getInstanceMethod([self class], @selector(insteadGetMethod)); if ([selectorString hasPrefix:@"set"]) { // method_getTypeEncoding()获取方法的类型编码(type encoding) class_addMethod(self, sel, class_getMethodImplementation(self, @selector(insteadSetMethod)), method_getTypeEncoding(exchangeSetM)); }else { class_addMethod(self, sel, class_getMethodImplementation(self, @selector(insteadGetMethod)), method_getTypeEncoding(exchangeGetM)); // 获取方法的类型编码(type encoding) } return YES;}- (void)insteadSetMethod { NSLog(@"调用了==== SET");}- (NSString *)insteadGetMethod { NSString *string = @"调用了==== GET 0001"; return string;}复制代码
重写resolveInstanceMethod:
方法,给找不到实现的方法添加set,get
方法。
动态添加属性
动态加载一个属性,只需利用分类机制就OK了,先看代码:
.h 文件#import@interface UIControl (Button)@property (nonatomic, assign) NSInteger clickCount;@end.m 文件#import "UIControl+Button.h"#import static const char *BtnClick_Key = "btn_clickkey";@implementation UIControl (Button)- (void)setClickCount:(NSInteger)clickCount { objc_setAssociatedObject(self, BtnClick_Key, @(clickCount), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (NSInteger)clickCount { return [objc_getAssociatedObject(self, BtnClick_Key) integerValue];}@end调用:UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];button.clickCount = 4;复制代码
通过上面代码,就可以动态添加属性。
objc_setAssociatedObject()
: set(源对象,key值,value值,属性关联策略)objc_getAssociatedObject()
: get(源对象,key值) 属性关联策略:
typedefOBJC_ENUM(uintptr_t, objc_AssociationPolicy){ // 第一个关联策略是基于基本类型的,也就是我们常用的assign 属性 OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. *///关联策略是基于对象类型的,如我们正常的是retain nonatomic (非原子操作)类型 ,retain : 保留一个引用指针,内存地址不修改,指向同一块内存地址 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. * The association is not made atomically. *///这个相当于属性中对一些对象或者字符串进行的copy 这个是拷贝一个新对象,内存地址不在一起,还是使用的非原子类型,非原子类型我们也称之为线程不安全的操作,但是对于OC里面的数据操作,我们尽量避开原子操作,原子操作是线程安全的,会影响我们对数据的写入操作 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied. * The association is not made atomically. */// 简单的指针引用, retain 操作 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. */};复制代码
获取对象的成员变量或属性
直接上代码
@protocol PersonDelegate- (void)setBackgroundWithColor1:(NSString *)string;@end@interface Person : NSObject@property (nonatomic, strong) NSString *name;@property (nonatomic, assign) NSInteger age;@property (nonatomic, assign) float weight;@property (nonatomic, copy) id delegate;- (void)testOne;- (void)changeTestString:(NSString *)string;@end#import "Person.h"@interface Person () { NSString *_decr;}@property (nonatomic, strong) NSString *title;@property (nonatomic, strong) UIView *testView;@end@implementation Person@end复制代码
使用class_copyIvarList
获取类的成员变量:
- (void)getInfoByIvar { unsigned int outCount = 0; Ivar *ivars = class_copyIvarList([Person class], &outCount); NSLog(@"ByIvar: %d", outCount); for (int i = 0; i < outCount; i ++) { const char *name = ivar_getName(ivars[i]); NSString *key = [NSString stringWithUTF8String:name]; NSLog(@"==== %@", key); } free(ivars);}复制代码
它返回的是一个Ivar
的数组,这个数组里面包含了你要查看类的所有实例变量,但是不包括从父类继承过来的。如果你传入的类没有实例变量或者改class
为Nil
,那么该方法返回的就是NULL
,count
值也就变成了0。有一点需要注意:你必须使用free()
方法将该数组释放。 然后就是通过for循环遍历,通过ivar_getName
拿到ivarName
。 以上便是对clas_copyIvarList
的介绍。
使用class_copyPropertyList
获取类的属性
- (void)getInfoByProperty { unsigned int outCount = 0; objc_property_t *property = class_copyPropertyList([Person class], &outCount); NSLog(@"ByProperty: %d", outCount); for (int i = 0; i < outCount; i ++) { NSString *name = @(property_getName(property[i])); NSString *attributes = @(property_getAttributes(property[i])); NSLog(@"==== %@ --------- %@", name, attributes); } free(property);}复制代码