美文网首页
iOS Runtime => 计算机原理 => 应用

iOS Runtime => 计算机原理 => 应用

作者: 处在水深火热的iOS_林龙 | 来源:发表于2018-03-21 16:52 被阅读0次

    在iOS开发中我们会用到的语言有《Objective-C》及 《swift》这两门语言。现在我们团队已经渐渐的从Objective-C转向Swift。由于产品已经有长远的历史了,不可能花上几个月的时间重新编写,所以我们采用的是混编的方式来解决这个问题,在新功能迭代时我们采用的是Swift开发。在维护旧功能时还是依旧使用Objective-C.虽然Swift并没有Runtime机制,但是只要继续用上Objective-C就有有可能会用到,所以这就是总结这篇文章的原因。Objective-C是一门动态性语言,通过Runtime机制实现运行时机制。说到这里,首先抛出一个问题,程序是如何运行跑起来的。如果不太清楚的话,先停下来思考几分钟再继续往下看。

    程序是如何跑起来的

    在我们目前编写的代码基本都是高级语言,计算机并不能识别这些语言。那从我们编写的语言是怎么转换为机器能识别的语言的,机器识别的语言又是怎么执行的?我们把这个思维调换一下方向,我们通过计算机为什么要这样做一步一步推倒回去。这样理解可能才是最有效的方式。

    人们都知道计算机只能识别0跟1,并不像人类所熟知的逢十进一,这是因为计算机的是使用二极管的方式,当通电时标识1,不通电标识0,现在的电脑普遍都是支持64位的,是因为继电器是64个二极管组成,同时能处理64个0跟1。只要我们把代码转化为0跟1那就可以让计算机识别。那我们就明白来了

    程序运行起来 < 机器识别语言(目标语言) < ( ???????? ) < 编程语言

    那我们现在就差一个问题,编程语言是如何装换为机器识别语言(目标语言)的?编程语言分底层语言,高阶(高级)语言,但是在一开始的时候并没有这样去分,刚开始人们想要让机器跑起来的编程语言就只有汇编语言,但由于编写汇编语言的人需要非常专业的工程师才能去编写,对比普通人来说门槛实在是太高了,聪(懒)明(惰)的人类想出了一个办法。编写一些让普通人能理解的语法,他们只负责调用就好,怎么实现他们不用管,这样就能大大降低了编程难度,也提高了编程效率。

    程序运行起来 < 机器识别语言(目标语言) < ( 汇编语言 ) < 编程语言

    现在我们来总结一下 :
    1.编写高级语言
    2.通过高级语言一步一步的转化为底层语言(汇编语言)
    3.通过底层语言(汇编语言)编译为机器识别语言(目标语言)
    4.程序跑起来了

    Runtime机制

    在Objective-C方法调用时,内部实现是通过消息发送的方式,编译器转换为objc_msgSend(receiver, selector)的函数调用。那为什么既然苹果已经封装的很好,尽量不使用C语言开发,那为什么这个Runtime会受到iOS开发者关注呢?那是因为Objective-C的特性,在编译时,程序只关注方法(函数)有没有声明,并不关注方法有没有实现,等到执行时才会加载(方法)函数内部的指令.通过该特性来实现iOS黑魔法(Method Swizzling)。

    通过这个特性可以实现的功能有:
    1.需要获取对象的所有属性及方法
    2.因为系统框架的达不到你要的效果,你需要对该框架进行修改。


    获取对象的所有属性及方法 , 实现字典转模型( sample 1.1 )
    # sample 1.1 
    @interface Person : NSObject
    @property (nonatomic,copy  )NSString* name;
    @property (nonatomic,copy  )NSString* address;
    @property (nonatomic,copy  )NSString* telephoneNumber;
    - (void)modelWithDictionary:(NSDictionary*)dictionary;
    @end
    
    @implementation Person
    - (void)modelWithDictionary:(NSDictionary*)dictionary {
        unsigned int outCount;
        // 获取对象有多少个属性
        objc_property_t * properties = class_copyPropertyList([self class], &outCount);
        //便利所有的属性
        for (int i = 0; i < outCount; i ++) {
            objc_property_t property = properties[i];
            // 获取该属性的属性名
            NSString* key =  [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
            // 如果该属性在字典里有值就赋值给该对象
            if (dictionary[key]) {
                [self setValue:dictionary[key] forKey:key];
            }
        }
    }
    @end
    
    
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSDictionary* dict = @{@"name":@"Lee Lei",@"telephoneNumber":@"10086",@"address":@"ShenZhen Guangdong China"};
        Person* p = [[Person alloc]init];
        [p modelWithDictionary:dict];
    }
    @end
    

    获取对象的所有属性及方法 , 实现NSCoding的自动归档和自动解档( sample 1.2 )
    # sample 1.2   注* 需要遵循NSCoding协议
    - (void)encodeWithCoder:(NSCoder *)aCoder {
        unsigned int outCount;
        // 获取对象有多少个属性
        objc_property_t * properties = class_copyPropertyList([self class], &outCount);
        //便利所有的属性
        for (int i = 0; i < outCount; i ++) {
            objc_property_t property = properties[i];
            // 获取该属性的属性名
            NSString* key =  [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
            [aCoder decodeObjectForKey:key];
        }
    }
    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
        self = [super init];
        if (self) {
            unsigned int outCount;
            objc_property_t * properties = class_copyPropertyList([self class], &outCount);
            //便利所有的属性
            for (int i = 0; i < outCount; i ++) {
                objc_property_t property = properties[i];
                // 获取该属性的属性名
                NSString* key =  [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
                [aDecoder encodeObject:[self valueForKey:key] forKey:key];
            }
        }
        return self;
    }
    

    因为系统框架的达不到你要的效果,当我们的URL包含有中文转为NSURL时会转换出错返回nil。我们需要对该字符串进行一个UTF8(encode)转码( sample 2.1 )
    # sample 2.1
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSURL* url = [NSURL URLWithString:@"https://wwww.baidu.com?a=哈喽"];
        NSLog(@"%@",url);
    }
    @end
    
    #import "NSURL+Runtime.h"
    #import <objc/runtime.h>
    @implementation NSURL (Runtime)
    + (void)load {
        Method beforeMethod = class_getClassMethod([self class], @selector(URLWithString:));
        Method afterMethod = class_getClassMethod([self class], @selector(ll_URLWithString:));
        method_exchangeImplementations(beforeMethod, afterMethod);
        
    }
    
    + (nullable instancetype)ll_URLWithString:(NSString *)URLString {
        URLString =  [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
        return [self ll_URLWithString:URLString];
    }
    @end
    

    相关文章

      网友评论

          本文标题:iOS Runtime => 计算机原理 => 应用

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