一、给分类加属性 分类中添加属性, .m文件中不会自动生成set及get方法, 需要在运行时进行关联绑定;

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

object:关联的源对象, key:关联此对象的标识, value:关联的对象 policy:关联策略,此处block属性用的copy, 关联策略就使用了 OBJC_ASSOCIATION_COPY_NONATOMIC

.h 中
typedef void(^TouchEvent)(UIButton *obj);

//给分类加block属性
@property (nonatomic, copy) TouchEvent event;

.m 中
static char *btn = "UIControlEventTouchUpInside";

- (void)setEvent:(TouchEvent)event {
objc_setAssociatedObject(self, &btn, event, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
//源对象根据key标识就能获取关联对象
- (TouchEvent)event {
return objc_getAssociatedObject(self, &btn);
}

二、关联对象 利用runtime可以把两个属性关联起来, 一个属性根据标识就能获取到另外一个对象

Person *per = [[Person alloc] init];
per.name = @"张三";

UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame =CGRectMake(30, 30, 60, 30);
[btn setTitle:@"点击" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];

//把对象per关联到btn上面
objc_setAssociatedObject(btn, "btn", per, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

- (void)clickBtn:(UIButton *)sender {
Person *per = (Person *)objc_getAssociatedObject(sender, "btn");
NSLog(@"===%@", per.name);
}
打印结果:
 ===张三

三、特殊情况下方法替换

method swizzling可以通过选择器来改变它引用的函数指针,从而实现方法替换

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    Class class = [self class];

    SEL originalSelector = @selector(viewWillAppear:);
    SEL swizzledSelector = @selector(sro_viewWillAppear:);

//获取实例方法        
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

    BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }

});
}

- (void)sro_viewWillAppear:(BOOL)animated {

//下面这段代码并没有死循环, method指针已经被替换, 会调用viewWillAppear方法
[self sro_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}

runtime在特殊的情况下还是很有用的,进一步学习中~

results matching ""

    No results matching ""