zoukankan      html  css  js  c++  java
  • IOS Runtime的用法

     什么是runtime?


    1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型、C语言函数)
    2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的
    * 也就是说,平时我们编写的OC代码,最终都是转成了底层的runtime代码(C语言代码)


    runtime有啥用?


    1> 能动态产生一个类、一个成员变量、一个方法
    2> 能动态修改一个类、一个成员变量、一个方法
    3> 能动态删除一个类、一个成员变量、一个方法


    常见的函数、头文件


    #import <objc/runtime.h> :           成员变量、类、方法
    Ivar * class_copyIvarList :              获得某个类内部的所有成员变量
    Method * class_copyMethodList :     获得某个类内部的所有方法
    Method class_getInstanceMethod :   获得某个实例方法(对象方法,减号-开头)
    Method class_getClassMethod :        获得某个类方法(加号+开头)
    method_exchangeImplementations : 交换2个方法的具体实现

    #import <objc/message.h> : 消息机制
    objc_msgSend(....)

    #import "HMViewController.h"
    #import "HMPerson.h"
    #import <objc/runtime.h>
    #import <objc/message.h>
    
    @interface HMViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *iconView1;
    @property (weak, nonatomic) IBOutlet UIImageView *iconView2;
    
    @property (nonatomic, strong) NSMutableArray *names;
    @property (nonatomic, strong) NSArray *books;
    
    @end
    
    @implementation HMViewController
    
    - (NSMutableArray *)names
    {
        if (_names == nil) {
            self.names = [NSMutableArray array];
        }
        return _names;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    //    NSDictionary *info = @{@"name" : @"jack", @"age" : @10};
    //    
    //    NSString *key = nil;
    //    
    //    NSLog(@"%@", info[key]);
        
        NSMutableDictionary *info = [NSMutableDictionary dictionary];
        info[@"name"] = nil;
        
    //    self.books = @[@"kiuhua", @"xxx"];
    //
    //    NSLog(@"%@", self.books[4]);
        
    //    [self addName:@"jack"];
    //    [self addName:@"rose"];
    //    [self addName:@"jim"];
    //
    //    NSLog(@"%@", self.names[4]);
    //    NSLog(@"%@", [self.names objectAtIndex:4]);
    }
    
    - (void)addName:(NSString *)name
    {
        [self.names addObject:name];
    }
    
    - (void)imageSwizzle
    {
        // 什么是iOS Swizzle?利用运行时函数交换2个方法的实现
        
        //    BOOL iOS7 = [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;
        //    if (iOS7) {
        //        self.iconView1.image = [UIImage imageNamed:@"face_os7"];
        //        self.iconView2.image = [UIImage imageNamed:@"vip_os7"];
        //    } else {
        //        self.iconView1.image = [UIImage imageNamed:@"face"];
        //        self.iconView2.image = [UIImage imageNamed:@"vip"];
        //    }
        self.iconView1.image = [UIImage imageNamed:@"face"];
        self.iconView2.image = [UIImage imageNamed:@"vip"];
    }
    
    - (void)testRuntimeIvar
    {
        // Ivar : 成员变量
        unsigned int count = 0;
        // 获得所有的成员变量
        Ivar *ivars = class_copyIvarList([HMPerson class], &count);
        for (int i = 0; i<count; i++) {
            // 取得i位置的成员变量
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            const char *type = ivar_getTypeEncoding(ivar);
            NSLog(@"%d %s %s", i, name, type);
        }
        
        //    HMPerson *p = [[HMPerson alloc] init];
        //    objc_msgSend(p, @selector(setAge:), 20);
        
        //    NSLog(@"%d", p.age);
    }

    HMPerson.h /.m(获取所有成员变量)

    #import <Foundation/Foundation.h>
    
    @interface HMPerson : NSObject <NSCoding>
    @property (nonatomic, assign) int age;
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) double height;
    - (void)run;
    @end
    View Code
    #import "HMPerson.h"
    #import <objc/runtime.h>
    
    @implementation HMPerson
    - (void)run
    {
        NSLog(@"run----");
    }
    
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([HMPerson class], &count);
        for (int i = 0; i<count; i++) {
            // 取得i位置的成员变量
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            NSString *key = [NSString stringWithUTF8String:name];
            [encoder encodeObject:[self valueForKeyPath:key] forKey:key];
        }
    }
    
    @end
    View Code

     UIImage+Extension(交换2个方法的实现)

    #import <objc/runtime.h>
    
    @implementation UIImage (Extension)
    /**
     *  只要分类被装载到内存中,就会调用1次
     */
    + (void)load
    {
        Method otherMehtod = class_getClassMethod(self, @selector(imageWithName:));
        Method originMehtod = class_getClassMethod(self, @selector(imageNamed:));
        // 交换2个方法的实现
        method_exchangeImplementations(otherMehtod, originMehtod);
    }
    
    + (UIImage *)imageWithName:(NSString *)name
    {
        BOOL iOS7 = [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;
        UIImage *image = nil;
        if (iOS7) {
            NSString *newName = [name stringByAppendingString:@"_os7"];
            image = [UIImage imageWithName:newName];
        }
        
        if (image == nil) {
            image = [UIImage imageWithName:name];
        }
        return image;
    }
    
    
    @end
    View Code

    NSObject+Extension(交换2个方法的实现)

    #import <objc/runtime.h>
    
    @implementation NSObject(Extension)
    + (void)swizzleClassMethod:(Class)class originSelector:(SEL)originSelector otherSelector:(SEL)otherSelector
    {
        Method otherMehtod = class_getClassMethod(class, otherSelector);
        Method originMehtod = class_getClassMethod(class, originSelector);
        // 交换2个方法的实现
        method_exchangeImplementations(otherMehtod, originMehtod);
    }
    
    + (void)swizzleInstanceMethod:(Class)class originSelector:(SEL)originSelector otherSelector:(SEL)otherSelector
    {
        Method otherMehtod = class_getInstanceMethod(class, otherSelector);
        Method originMehtod = class_getInstanceMethod(class, originSelector);
        // 交换2个方法的实现
        method_exchangeImplementations(otherMehtod, originMehtod);
    }
    @end
    
    @implementation NSArray(Extension)
    + (void)load
    {
        [self swizzleInstanceMethod:NSClassFromString(@"__NSArrayI") originSelector:@selector(objectAtIndex:) otherSelector:@selector(hm_objectAtIndex:)];
    }
    
    - (id)hm_objectAtIndex:(NSUInteger)index
    {
        if (index < self.count) {
            return [self hm_objectAtIndex:index];
        } else {
            return nil;
        }
    }
    
    @end
    
    @implementation NSMutableArray(Extension)
    + (void)load
    {
        [self swizzleInstanceMethod:NSClassFromString(@"__NSArrayM") originSelector:@selector(addObject:) otherSelector:@selector(hm_addObject:)];
        [self swizzleInstanceMethod:NSClassFromString(@"__NSArrayM") originSelector:@selector(objectAtIndex:) otherSelector:@selector(hm_objectAtIndex:)];
    }
    
    - (void)hm_addObject:(id)object
    {
        if (object != nil) {
            [self hm_addObject:object];
        }
    }
    
    - (id)hm_objectAtIndex:(NSUInteger)index
    {
        if (index < self.count) {
            return [self hm_objectAtIndex:index];
        } else {
            return nil;
        }
    }
    @end
    View Code

     

  • 相关阅读:
    排序
    Apache架设Web服务器
    函数调用规范
    linux启动流程
    Make工程管理器
    网络相关知识
    数字电路中的建立时间与保持时间
    面试碰到的技术题
    嵌入式linux的驱动程序
    EF实体中的修改
  • 原文地址:https://www.cnblogs.com/liuwj/p/6752679.html
Copyright © 2011-2022 走看看