IOS 运行时(runtime)机制

1. 概述

OC 是一个全动态语言,OC 的一切都是基于 Runtime 实现的

只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法`

2. 运行时机制

运行时机制是用 C++ 开发的,是一套苹果开源的框架

OC 是基于运行时开发的语言

3. 应用场景

运行时动态获取类的属性

主要应用:

  • 字典转模型框架 MJExtension,JSONModel
  • 利用 关联对象 为分类添加属性
  • 利用 交换方法 拦截系统或其他框架的方法
  • 误区:并不是使用的技术越底层,框架的效率就会越高

导入头文件

#import <objc/runtime.h>

4. 示例

为NSObject添加一个分类

//
//  NSObject+Extension.m
//

#import "NSObject+Extension.h"
#import <objc/runtime.h>

@implementation NSObject (Extension)

const char *propertiesKey = "propertiesKey";
const char *methodsKey = "methodsKey";
const char *protocolKey = "protocolKey";

/// 字典转模型方法
+ (instancetype)objectWithDict:(NSDictionary *)dict
{
    id obj = [[self alloc] init];

    // 获取属性列表
    NSArray *properties = [self propertyList];

    // 遍历属性数组
    for (NSString *key in properties)
    {
        // 判断字典中是否包含这个key
        if (dict[key] != nil)
        {
            // 使用 KVC 设置属性值
            [obj setValue:dict[key] forKeyPath:key];
        }
    }

    return obj;
}

/**
 如果能够自动生成这个数组,就好了!
 如果要想动态的获取类的属性,需要使用到“运行时机制”

 class_copyIvarList 成员变量,提示有很多第三方框架会使用 Ivar,能够获得更多的信息
 但是:在 swift 中,由于语法结构的变化,使用 Ivar 非常不稳定,经常会崩溃!
 class_copyPropertyList 属性
 class_copyMethodList 方法
 class_copyProtocolList 协议
 */
/// 返回类的属性列表
+ (NSArray *)propertyList
{

    // 0. 判断是否存在关联对象, 如果存在, 直接返回
    /** 参数
     1> 关联到得对象
     2> 关联的属性 key
     */
    NSArray *plist = objc_getAssociatedObject(self, propertiesKey);
    if (plist)
    {
        return plist;
    }

    // 1. 获取 ‘类的属性‘
    /**
     1> 类
     2> 属性的计数指针
     */
    unsigned int count = 0;
    // 返回值是所有属性的数组 obj_property_
    objc_property_t *list = class_copyPropertyList([self class], &count);

    // 创建 存储属性数组
    NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];

    for (int i = 0; i < count; ++i)
    {

        // 获取属性
        objc_property_t pty = list[i];

        // 获取属性名
        const char *cname = property_getName(pty);
        [arrayM addObject:[NSString stringWithUTF8String:cname]];
    }

    // 释放属性数组
    free(list);

    // 设置关联对象
    /**
     1> 关联的对象
     2> 关联对象的 key
     3> 属性数值
     4> 属性的持有方式 reatin, copy, assign
     */
    objc_setAssociatedObject(self, propertiesKey, arrayM, OBJC_ASSOCIATION_COPY_NONATOMIC);

    return arrayM.copy;
}

/// 返回类的方法列表
+ (NSArray *)methodList
{

    // 0. 判断是否存在依赖关系
    NSArray *mlist = objc_getAssociatedObject(self, methodsKey);
    if (mlist)
    {
        return mlist;
    }

    unsigned int count = 0;
    // 1. 获取方法列表
    Method *list = class_copyMethodList([self class], &count);

    // 存储方法数组
    NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];

    for (int i = 0; i < count; ++i)
    {
        // 获取方法
        Method method = list[i];
        // 获取方法名
        SEL mname = method_getName(method);

        [arrayM addObject: NSStringFromSelector(mname)];
    }

    // 释放数组
    free(list);

    // 设置依赖关系
    objc_setAssociatedObject(self, methodsKey, arrayM, OBJC_ASSOCIATION_COPY_NONATOMIC);

    return arrayM.copy;
}

/// 返回类的实现协议列表
+ (NSArray *)protocolList
{

    // 0. 判断是否存在依赖关系
    NSArray *pList = objc_getAssociatedObject(self, protocolKey);
    if (pList)
    {
        return pList;
    }

    unsigned int count = 0;
    // 2. 获取协议列表
    Protocol * __unsafe_unretained *list = class_copyProtocolList([self class], &count);

    // 创建协议数组
    NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];

    for (int i = 0; i < count; ++i)
    {

        // 获取协议
        Protocol * __unsafe_unretained prot = list[i];

        const char *pname = protocol_getName(prot);

        [arrayM addObject:[NSString stringWithUTF8String:pname]];
    }

    return arrayM;
}
@end
时间: 2024-10-15 02:36:47

IOS 运行时(runtime)机制的相关文章

iOS运行时 -- Runtime(摘抄自网络)

运行时(iOS) 一.什么是运行时(Runtime)? 运行时是苹果提供的纯C语言的开发库(运行时是一种非常牛逼.开发中经常用到的底层技术) 二.运行时的作用? 能获得某个类的所有成员变量 能获得某个类的所有属性 能获得某个类的所有方法 交换方法实现 能动态添加一个成员变量 能动态添加一个属性 能动态添加一个方法 三.案例:运行时获取成员变量名称 1.分析 #import <Foundation/Foundation.h> #import "XMGPerson.h" #im

iOS 运行时添加属性和方法

原文链接http://blog.csdn.net/meegomeego/article/details/18356169第一种:runtime.h里的方法 BOOL class_addProperty(Class cls,constchar*name,constobjc_property_attribute_t*attributes,unsignedint attributeCount) #include <objc/runtime.h> #import <Foundation/Foun

iOS运行时编程(Runtime Programming)和Java的反射机制对比

运行时进行编程,类似Java的反射.运行时编程和Java反射的对比如下: 1.相同点 都可以实现的功能:获取类信息.属性设置获取.类的动态加载(NSClassFromString(@“className”)).方法的动态调用 下面是iOS中涉及到的相关使用方法 类的动态加载:NSClassFromString(@“className”),方法的动态调用:NSSelectorFormString(@”doSonethingMethod:”) 常见的方法: isKindOfClass: isMemb

iOS 运行时详解

注:本篇文章转自:http://www.jianshu.com/p/adf0d566c887 一.运行时简介 Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行.Runtime基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力.在Runtime中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上了一些额外的特性.这些结构体和

iOS 运行时应用

一.什么是运行时(Runtime)? 运行时是苹果提供的纯C语言的开发库(运行时是开发中经常用到的底层技术) 二.运行时的作用? 能获得某个类的所有成员变量 能获得某个类的所有属性 能获得某个类的所有方法 交换方法实现 能动态添加一个成员变量 能动态添加一个属性 能动态添加一个方法 三.案例:运行时获取成员变量名称 1.分析 #import <Foundation/Foundation.h> #import "CKPerson.h" #import <objc/run

iOS开发之Runtime机制深入解析

本篇主要讲述在 OC 开发中主要涉及到的运行时机制: 运行时的工作: 运行时在 OC 中的工作:OC 语言的设计模式决定了尽可能的把程序从编译和链接时推迟到运行时.只要有可能,OC 总是使用动态的方式来解决问题.这意味着 OC 语言不仅需要一个编译器,同时也需要一个运行时系统来执行编译好的代码.这儿的运行时系统扮演的角色类似于 OC 语言的操作系统,OC 基于该系统来工作.  运行时的简单应用: OC 2.0运行时系统参考库描述了OC 运行库的数据结构和函数接口.程序可以通过这些接口来和 OC

iOS运行时工具-cycript

cycript是大神saurik开发的一个非常强大的工具,可以让开发者在命令行下和应用交互,在运行时查看和修改应用.它确实可以帮助你破解一些应用,但我觉得这个工具主要还是用来学习其他应用的设计(主要是UI的设计及实现). 这个工具使用了Objective-C和Javascript的混合模式,可以实时的和应用交互甚至修改应用.它的网址请猛戳这里.在官网上可以下载到完整的软件包.使用的方式有两种,一种是在越狱的设备上通过MobileSubstrate加装,这样可以在所有的应用里使用:另一种是通过静态

IOS运行时动态注册字体

在IOS开发中,使用第三方字体,如ttf文件,otf文件,是很简单的.只需要两个步骤.1,讲 ttf文件,otf文件添加到工程根目录中.2,在info.plist中增加字体文件,是字体文件名.在使用时,双击打开字体文件,标题会显示字体名称,使用那个自体名称(setFontName)即可.在android中,是把字体文件拷贝到asset目录中,再使用typeface类根据文件得到其实例. 现在的问题是,在我们玩图的开发中,由于中文字体过大,需要从线上下载,下载到本地使用,这就涉及到一个注册字体问题

iOS 运行时判断xib是否存在

知识要点 1.  xib最终会变成nib文件 2.  NSBundle实例方法  - (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext; 如果bundle中不存在某个文件,则返回的path为nil,如果存在 则会返回该文件的路径 因此运行时判断xib是否存在某个xib文件(eg:TestXibController.xib)方法: NSString *nibPath = [[NSBundle mainBundle

我理解的iOS中的RunTime机制(1)

一.首先我们要先知道object-c是一门编译型.动态语言(这里强调下oc是静态类型语言),这在开发语言中是并多见的,一般的动态语言多为解释性语言.oc之所以能够做到即使编译型语言,又是动态语言.就是得益于RunTime机制. 由于本文主要讲解的是RunTime机制,所以语言类型不做过多描述,之后可以另写一篇语言类型的介绍. 二.这里主要讲解RunTime如何使用,其中主要的知识点如下: 1.class_copyPropertyList  获取一份拷贝的成员列表数组 2.property_get