美文网首页iOS
iOS runtime实用案例

iOS runtime实用案例

作者: aqaqa | 来源:发表于2017-02-09 17:30 被阅读11次
    案例一:避免向一个数组中加入nil时导致崩溃
    • 交换方法实现swizzle(+load 和 dispatch_once_t 能有效保证安全);
    • 获取类的实例方法class_getInstanceMethod,对应获取类的类方法class_getClassMethod
    +(void)load{
        [self swizzleMethod:@selector(addObject:) anotherMethod:@selector(safeAddObject:)];
    }
    
    + (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel{
         static dispatch_once_t onceToken;
         dispatch_once(&onceToken, ^{
         Method oneMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), oneself);//类的真名
         Method anotherMethod = class_getInstanceMethod(self, anotherSel);
         if (!oneMethod || !anotherMethod) return;
         method_exchangeImplementations(oneMethod, anotherMethod);
    });
    }
    
    - (void)safeAddObject:(id)obj {
         if (obj != nil) {
              [self safeAddObject:obj];//不会导致递归
         } else {
              NSLog(@"数组不能加入nil object");
         }
    }
    @end
    
    
    案例二:防止按钮重复点击
    • 关联属性Associated object
    #import "UIControl+Safety.h"
    #import <objc/runtime.h>
    static const char kSafety_ignoreEventTime;//按钮点击的时间
    static const char kSafety_acceptEventInterval;//按钮点击的时间间隔
    @interface UIControl ()
    @property (nonatomic, assign) NSTimeInterval safety_ignoreEventTime;
    @end
    @implementation UIControl (Safety)
    +(void)load {
        [self swizzleMethod:@selector(sendAction:to:forEvent:) anotherMethod:@selector(safety_sendAction:to:forEvent:)];
    }
    + (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Method oneMethod = class_getInstanceMethod(self, oneSel);
            Method anotherMethod = class_getInstanceMethod(self, anotherSel);
            if (!oneMethod || !anotherMethod) return;
            method_exchangeImplementations(oneMethod, anotherMethod);
        });
    }
    - (void)safety_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
        if (NSDate.date.timeIntervalSince1970 - self.safety_ignoreEventTime < self.safety_acceptEventInterval) {
            return;
        }
        
        if (self.safety_acceptEventInterval > 0) {
            self.safety_ignoreEventTime = NSDate.date.timeIntervalSince1970;
        }
        [self safety_sendAction:action to:target forEvent:event];
    }
    
    #pragma mark property 关联属性
    - (NSTimeInterval)safety_ignoreEventTime {
        return [objc_getAssociatedObject(self, &kSafety_ignoreEventTime) doubleValue];
    }
    
    - (void)setSafety_ignoreEventTime:(NSTimeInterval)safety_ignoreEventTime {
        objc_setAssociatedObject(self, &kSafety_ignoreEventTime, @(safety_ignoreEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSTimeInterval)safety_acceptEventInterval {
        return [objc_getAssociatedObject(self, &kSafety_acceptEventInterval) doubleValue];
    }
    
    - (void)setSafety_acceptEventInterval:(NSTimeInterval)safety_acceptEventInterval {
        objc_setAssociatedObject(self, &kSafety_acceptEventInterval, @(safety_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    @end
    
    案例三:字典转模型原理

    相关文章

      网友评论

        本文标题:iOS runtime实用案例

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