美文网首页
iOS -- runtime的应用

iOS -- runtime的应用

作者: iOS程序媛ing | 来源:发表于2020-09-10 10:20 被阅读0次

runtime主要有一下几种应用场景

  • 方法交换
  • 添加属性

(一)方法交换

(1)字体适配

//获取实例方法
Method n = class_getInstanceMethod(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull name#>)
//获取类方法
Method m = class_getClassMethod(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull name#>)
//交换方法
method_exchangeImplementations(<#Method  _Nonnull m1#>, <#Method  _Nonnull m2#>)

方法交换实际交换的是方法实现的地址

//load方法不需要手动调用,iOS会在应用程序启动的时候自动调起load方法,而且执行时间较早,所以在此方法中执行交换操作比较合适。
+ (void)load {
    Method orignal = class_getClassMethod([self class], @selector(systemFontOfSize:));
    Method mjfont = class_getClassMethod([self class], @selector(mjfontOfSize:));
    method_exchangeImplementations(orignal, mjfont);
}

+ (UIFont *)mjfontOfSize:(CGFloat)size {
    if (ScreenWidth == 375) {
        return [self mjfontOfSize:size];
    }
    return [self mjfontOfSize:size + 10];
}

(2)button防止重复点击
①在.h文件中声明时间属性,用于设置多长时间不能重复点击

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIButton (Category)

@property (nonatomic, assign) NSTimeInterval timerInterval;
@property (nonatomic, assign) BOOL isOk;

@end

②在.m文件中声明是否可以点击属性

#import "UIButton+Category.h"
#import <objc/runtime.h>

@interface UIButton ()
@property (nonatomic, assign) BOOL isOk;
@end

③添加属性的set、get方法,实现方法交换

+ (void)load {

    Method orignal = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));
    Method mjSend = class_getInstanceMethod([self class], @selector(mjsendAction:to:forEvent:));
    method_exchangeImplementations(orignal, mjSend);
}

- (void)mjsendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
 
    if (!self.isOk) {
        self.isOk = YES;
        [self mjsendAction:action to:target forEvent:event];
//重设是否可以点击
        [self performSelector:@selector(resetOK) withObject:nil afterDelay:self.timerInterval];
    }
}

- (void)setIsOk:(BOOL)isOk {
    objc_setAssociatedObject(self, @selector(isOk), @(isOk), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)isOk {
    return[objc_getAssociatedObject(self,_cmd)boolValue];
}


- (void)setTimerInterval:(NSTimeInterval)timerInterval {
    objc_setAssociatedObject(self, @selector(timerInterval), @(timerInterval), OBJC_ASSOCIATION_ASSIGN);
}

- (NSTimeInterval)timerInterval {
    return[objc_getAssociatedObject(self,_cmd)doubleValue];
}

- (void)resetOK {
    self.isOk = NO;
}

(二)添加属性---关联对象方法

如:给UIView添加一个name的属性
//①首先声明属性

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIView (Category)

@property (nonatomic, strong) NSString *name;

@end

NS_ASSUME_NONNULL_END

②添加set、get方法实现

#import "UIView+Category.h"
#import <objc/runtime.h>

@implementation UIView (Category)
    /*
     object  需要设置关联属性的对象,即给谁关联属性
     key     关联属性对应的key,可通过key获取这个属性
     value   给关联属性设置的值
     objc_AssociationPolicy policy  关联属性的存储协议
     */
    objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>)
- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY);
}
/*
     object 需要关联属性的对象,即给谁关联属性
     value  关联属性对应的key,可以通过这个key找到关联属性
     */
    objc_getAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>)
- (NSString *)name {
    
    return objc_getAssociatedObject(self, @selector(name));
}

@end

相关文章

网友评论

      本文标题:iOS -- runtime的应用

      本文链接:https://www.haomeiwen.com/subject/qsyuektx.html