runtime 应用

1. 交换方法

1.1 获取类方法

Method class_getClassMethod(Class cls , SEL name)

1.2 获取实例方法

Method class_getInstanceMethod(Class cls , SEL name)

1.3 交换两个方法

void method_exchangeImplementations(Method m1 , Method m2)

实例:

//Person.h
#import 

@interface Person : NSObject

+ (void)method_1;

+ (void)method_2;

- (void)method_3;

- (void)method_4;

@end

//Person.m
#import "Person.h"

@implementation Person

+ (void)method_1
{
    NSLog(@"method_1");
}

+ (void)method_2
{
    NSLog(@"method_2");
}

- (void)method_3
{
    NSLog(@"method_3");
}

- (void)method_4
{
    NSLog(@"emthod_4");
}

@end


        [Person method_1]; //log: method_1
        [Person method_2];  //log: method_2
        
        Method m1 = class_getClassMethod([Person class], @selector(method_1));
        Method m2 = class_getClassMethod([Person class], @selector(method_2));
        method_exchangeImplementations(m1, m2);
        
        [Person method_1]; //log: method_2
        [Person method_2]; //log: method_1
        
        Person *p = [[Person alloc] init];
        [p method_3];   //log: method_3
        [p method_4];   //log: method_4
        
        Method m3 = class_getInstanceMethod([Person class], @selector(method_3));
        Method m4 = class_getInstanceMethod([Person class], @selector(method_4));
        method_exchangeImplementations(m3, m4);
        
        [p method_3];   //log: method_4
        [p method_4];   //log: method_3

2. 分类添加属性

下面给NSObject添加一个name属性

#import 

@interface NSObject (Category)


@property (nonatomic, strong)   NSString *name;

@end


#import "NSObject+Category.h"
#import 

const char * str = "myKey";


@implementation NSObject (Category)

- (void)setName:(NSString *)name
{
    /**
     *  void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)
     *  object  需要添加属性的对象
     *  key     属性的key, 将来可以通过key取出这个存储的值
     *  value   属性的值
     *  policy  使用的策略,是一个枚举值,可根据开发需要选择不同的枚举
     */
    objc_setAssociatedObject(self, &str, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSString *)name
{
    return objc_getAssociatedObject(self, &str);
}

@end

3. 消息拦截转发

用到的几个方法

+ (BOOL)resolveInstanceMethod:(SEL)sel
+ (BOOL)resolveClassMethod:(SEL)sel
- (id)forwardingTargetForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
//对当前类添加一个newTestMethod方法, 当testMethod没有实现时, runtime会进行消息转发
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    // 指定对某一个方法的动态解析
    NSString *selName = NSStringFromSelector(sel);
    if ([selName isEqualToString:@"testMethod"]) {
        // 动态的添加一个方法
        class_addMethod([self class], @selector(testMethod), (IMP)newTestMethod, "v@:");
        return YES;
    }
    return NO;
}

void newTestMethod()
{
    NSLog(@"%s", __func__);
}

3.2 消息转发到其他类

// 我们首先要通过, 指定方法签名,若返回nil,则表示不处理。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSLog(@"指定方法签名");
    NSString *selName = NSStringFromSelector(aSelector);
    if ([selName isEqualToString:@"testMethod"]) {
        
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    
    return [super methodSignatureForSelector:aSelector];
}

// 通过anInvocation对象做很多处理,比如修改实现方法,修改响应对象等
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    NSLog(@"%s", __func__);
    // 改变响应对象并改变响应方法
    [anInvocation setSelector:@selector(newTestMethod)];
    [anInvocation invokeWithTarget:[ZYChildren new]];
}

//跳转到其他类中执行
- (id)forwardingTargetForSelector:(SEL)aSelector
 {
     NSLog(@"备用接收者");
 // 指定对某一个对象来执行方法
     NSString *selName = NSStringFromSelector(aSelector);
     if ([selName isEqualToString:@"testMethod"]) {
 
         return [ZYChildren new];
     }
     return [super forwardingTargetForSelector:aSelector];;
 }

        //拦截调用
        MyClass *myClass = [[MyClass alloc] init];
        [myClass performSelector: @selector(testMethod) withObject: @"test"];

4. 其他用法

 unsigned int count;
         //获取属性列表
        objc_property_t *propertyList = class_copyPropertyList([MyClass class], &count);
        for (unsigned int i = 0; i < count; i ++)
        {
            const char *propertyName = property_getName(propertyList[i]);
            NSLog(@"property ----> %@", [NSString stringWithUTF8String: propertyName]);
        }
    
         //获取实例方法列表
        Method *methodList = class_copyMethodList([MyClass class], &count);
        for (unsigned int i = 0; i < count; i ++)
        {
            Method method = methodList[i];
            NSLog(@"method ----> %@", NSStringFromSelector(method_getName(method)));
        }
         
    
        //获取成员变量列表
        Ivar *ivarList = class_copyIvarList([MyClass class], &count);
        for (unsigned int i = 0; i < count; i ++)
        {
            Ivar myIvar = ivarList[i];
            const char *ivarName = ivar_getName(myIvar);
            NSLog(@"Ivar ----> %@", [NSString stringWithUTF8String: ivarName]);
        }
         
        
        //获取协议列表
        __unsafe_unretained Protocol **protocolList = class_copyProtocolList([MyClass class], &count);
        for (unsigned int i = 0; i < count; i ++)
        {
            Protocol *myProtocal = protocolList[i];
            const char *protocolName = protocol_getName(myProtocal);
            NSLog(@"protocol ----> %@", [NSString stringWithUTF8String: protocolName]);
        }

你可能感兴趣的:(runtime 应用)