动态解析实现@dynamic属性、动态添加属以及获取类的实例变量和属性

以动态解析来实现@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 <UIKit/UIKit.h>
@interface UIControl (Button)
@property (nonatomic, assign) NSInteger clickCount;
@end

.m 文件
#import "UIControl+Button.h"
#import <objc/runtime.h>
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 <NSObject>
- (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<PersonDelegate>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的数组,这个数组里面包含了你要查看类的所有实例变量,但是不包括从父类继承过来的。如果你传入的类没有实例变量或者改classNil,那么该方法返回的就是NULLcount值也就变成了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);
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值