runtime

作者: 西门淋雨 | 来源:发表于2018-08-14 15:12 被阅读8次

    给NSObject增加属性

    #import <Foundation/Foundation.h>
    
    @interface NSObject (runtime)
    @property(nonatomic,strong)NSString *myTitle;
    @end
    
    #import "NSObject+runtime.h"
    #import <objc/runtime.h>
    static NSString *const kName = @"kName";
    static NSString *const kTitle = @"kTitle";
    
    @implementation NSObject (runtime)
    
    - (void)setMyTitle:(NSString *)myTitle{
        objc_setAssociatedObject(self, &kTitle, myTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    -(NSString *)myTitle{
        return objc_getAssociatedObject(self, &kTitle);
    }
    @end
    

    弹框

    #import <UIKit/UIKit.h>
    typedef void (^AlertCallBlock)(NSInteger buttonIndex);
    @interface UIAlertView (runtime)
    - (void)showAlertWithBlock:(AlertCallBlock)block;
    @end
    
    #import "UIAlertView+runtime.h"
    #import <objc/runtime.h>
    static NSString *const kBlockKey = @"kBlockKey";
    @implementation UIAlertView (runtime)
    - (void)showAlertWithBlock:(AlertCallBlock)block{
        self.delegate = self;
        objc_setAssociatedObject(self, &kBlockKey, block, OBJC_ASSOCIATION_COPY);
        [self show];
    }
    - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
        //根据给定的键从某对象中获取相应的关联对象值
        AlertCallBlock alertCallBack = objc_getAssociatedObject(self, &kBlockKey);
        if (alertCallBack) {
            alertCallBack(buttonIndex);
            objc_setAssociatedObject(self, &kBlockKey, nil, OBJC_ASSOCIATION_COPY);
        }
    }
    @end
    

    Method Swizzling方法交换封装

    /*************NSObject+Swizzling.h******************/
    #import <objc/runtime.h>
    @interface NSObject (Swizzling) 
    
    + (void)methodSwizzlingWithOriginalSelector:(SEL)originalSelector
                             bySwizzledSelector:(SEL)swizzledSelector;
    @end
    
    /*************NSObject+Swizzling.m******************/
    #import "NSObject+Swizzling.h"
    @implementation NSObject (Swizzling)
    
    + (void)methodSwizzlingWithOriginalSelector:(SEL)originalSelector bySwizzledSelector:(SEL)swizzledSelector{
        Class class = [self class];
        //原有方法
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        //替换原有方法的新方法
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    /**
    先尝试給源SEL添加IMP,这里是为了避免源SEL没有实现IMP的情况.
    class_addMethod会添加一个覆盖父类的实现,但不会取代原有类的实现。
    也就是说如果class_addMethod返回YES,说明子类中没有方originalSelector,
    通过class_addMethod为其添加了方法originalSelector,并使其实现(IMP)为我们想要替换的实现。
    */
        BOOL didAddMethod = class_addMethod(class,originalSelector,
                                            method_getImplementation(swizzledMethod),
                                            method_getTypeEncoding(swizzledMethod));
        if (didAddMethod) {//添加成功:说明源SEL没有实现IMP,将源SEL的IMP替换到交换SEL的IMP
            class_replaceMethod(class,swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {//添加失败:说明源SEL已经有IMP,直接将两个SEL的IMP交换即可
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
    @end
    
    

    分类可以添加@property的属性,但是仅仅是自动生成了get和set方法,并没有带下划线的属性和方法实现生成,但是runtime可以实现。
    原理:给一个类声明属性,本质是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间。

    相关文章

      网友评论

          本文标题:runtime

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