原创

oc runtime

Person *p = [Person alloc];

p = [p init];

可以写成

Person *p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));

p = objc_msgSend(p, @selector(init));

获取一个类的所有方法(包括属性的get和set的方法),必须导入库 #import <objc/runtime.h>

unsigned int count = 0;

// 调用完这个方法,count就有值,记录方法列表总数

// 获取仅仅是当前类

// 返回指向方法列表数组

    Method *methodList = class_copyMethodList([Person class], &count);

// 2 0 1

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

// 取出对应的方法

        Method method = methodList[i];

// 获取方法名(方法编号)

        SEL methodSel =  method_getName(method);

        NSLog(@"%@",NSStringFromSelector(methodSel));

    }

//通过runtime获得类中属性的列表 不包含.m中的 @property属性

//就是返回的属性个数,也就是返回值的数组的count

unsigned int outCount;

    objc_property_t * propertys = class_copyPropertyList(clazz, &outCount);

for(int i = 0; i < outCount;i++)

    {

//取出具体的某一个属性

        objc_property_t property = propertys[i];

//获得类属性的名称

const char * propertyName = property_getName(property);

//转换成oc字符串

NSString * propertyNameOC = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];

//NSLog(@"%@",propertyNameOC);

//attributes 中获得重要信息

//1.属性的数据类型是什么

//2.属性与那个成员变量相关联

const char * attributes = property_getAttributes(property);

NSString * attributesString = [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding];

//NSLog(@"%@",attributesString);

    }

    方法交换适用于重写初始化

    Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));

// 获取yc_imageNamed方法

    Method yc_imageNameMethod = class_getClassMethod(self, @selector(yc_imageNamed:));

// 交换方法实现

    method_exchangeImplementations(imageNameMethod, yc_imageNameMethod);

动态添加属性

#import "NSObject+Property.h"

#import <objc/message.h>

@implementation NSObject (Property)

- (void)setName:(NSString *)name

{

// name保存到对应对象

// 动态添加属性

// object:给那个对象添加属性

// key:属性名

// value:把什么对象保存起来

// policy:策略,用什么策略

    objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (NSString *)name

{

return objc_getAssociatedObject(self, @"name");

}

 案例请查看uitextfiled扩展类修改placeholder的颜色

动态添加方法带参数  开发场景:如果一个类方法非常多,加载了到内存的时候也比较耗费资源,需给每个方法生成映射表,可以使用动态给某个类,添加方法解决

#Person.m文件中

// C语言中所有对象类型用 id

void conan_eat(id self, SEL _cmd, id prame1){

NSLog(@“调用eat方法 %@ %@ %@",self,NSStringFromSelector(_cmd),prame1);

}

+ (BOOL)resolveInstanceMethod:(SEL)sel{

// 动态添加未实现的方法

if (sel == @selector(eat:)) {

/**

         v : void

         @ : 对象

         : : SEL

         */

        class_addMethod(self, sel, (IMP)conan_eat, "v@:@");

// 处理完

return YES;

    }

return [super resolveInstanceMethod:sel];

}

#ViewControllers中

 [p performSelector:@selector(eat:) withObject:@11];

动态添加方法不带参数

#import "Person.h"

#import <objc/message.h>

@implementation Person

/**

 默认一个方法都有两个参数,self,_cmd,为隐式参数,不显示

 self :方法的调用者

 _cmd :调用方法的编号,即方法名

 */

//1. 定义一个函数(函数名随便写)

// 无返回值,参数(id,SEL)

void tangtang_eat(id self, SEL _cmd){

NSLog(@"调用糖糖的eat方法 %@ %@",self,NSStringFromSelector(_cmd));

}

/**

 2.处理为实现的实例方法

 动态添加方法,首先实现这个resolveInstanceMethod方法

 resolveInstanceMethod调用的情况:当调用了一个没有实现的方法,就会调用resolveInstanceMethod这个方法

 <#sel#>:没有实现的方法

 */

+ (BOOL)resolveInstanceMethod:(SEL)sel{

// 动态添加未实现的方法

if (sel == @selector(eat)) {

/**

         v : void

         @ : 对象

         : : SEL

         */

        class_addMethod(self, sel, (IMP)tangtang_eat, "v@:");

// 处理完

return YES;

    }

return [super resolveInstanceMethod:sel];

}

@end

#在viewController中

- (void)viewDidLoad {

    [super viewDidLoad];

    Person *p = [[Person alloc]init];

//performSelector:即为动态添加方法

    [p performSelector:@selector(eat)];

}

获取加方法  :  class_getClassMethod 

获取减方法   :  class_getInstanceMethod   

method_exchangeImplementations( 方法1,方法2 );

Class的各项操作

3.1 add*(增加)

3.1.1 static IMP addMethod(Class cls, SEL name, IMP imp, const char *types, BOOL replace);//增加方法

3.1.2 BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);//增加类方法

3.1.3 BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *type);//增加实例变量

3.1.4 static BOOL _class_addProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int count,BOOL replace);//增加属性

3.2 replace*(修改)

3.2.1 IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types); //修改方法

3.2.2 void class_replaceProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int n);//修改属性

3.3 get*(获取)

3.3.1 static Class getClass(const char *name);//获取类

3.3.2 static ivar_t *getIvar(Class cls, const char *name);//获取类变量(static相当于“+“)

3.3.3 Method class_getInstanceMethod(Class cls, SEL sel);//获取实例方法

3.3.4 static Method _class_getMethod(Class cls, SEL sel);;//获取类方法

3.3.5 static Protocol *getProtocol(const char *name);//获取协议方法

3.4 set*(设置)

3.4.1 objc_class::setInitialized();//set的initialized初始化

3.4.2 static Class setSuperclass(Class cls, Class newSuper);//设置父类

3.5 其他还有类似于 void *objc_destructInstance(id obj);//摧毁实例对象等等

Class的重要函数

4.1 get*(获取)

4.1.1 object_getClass(id obj);

4.1.2 IMP object_getMethodImplementation(id obj, SEL name);//获得实例方法实现

4.1.3 Ivar object_getInstanceVariable(id obj, const char *name, void **value)//获取实例属性

    4.2 set*(设置)

        4.2.1 Class object_setClass(id obj, Class cls);

4.2.2 Ivar object_setInstanceVariable(id obj, const char *name, void *value);//设置实例属性

4.2.3 void object_setIvar(id obj, Ivar ivar, id value);//设置实例变量

4.3 其他

4.3.1 static void _class_resolveClassMethod(Class cls, SEL sel, id inst);//动态添加类方法,不必在乎方法是否存在

4.3.2 static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst);//动态添加实现方法,不必在乎方法是否存在

4.3.3 unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone,id *results, unsigned num_requested);//创建实例存储空间

4.4 消息转发

4.4.1 void instrumentObjcMessageSends(BOOL flag);//flag传入YES,运行时发送的所有消息都会打印到/tmp/msgSend-xxxx文件里了。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • OC底层探索-Runtime简介OC底层探索-Runtime简介

    用户8893176
  • iOS运行时Runtime基础

    梧雨北辰
  • OC最实用的runtime总结,面试、工作你看我就足够了!前言什么是runtime?如何应用运行时?

    用户2141756
  • iOS runtime探究(一): 从runtime开始理解面向对象的类到面向过程的结构体你要知道的runtime都在这里

    你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解...

    WWWWDotPNG
  • run timeimport : 成员变量、类、方法

    且行且珍惜_iOS
  • Swift Runtime ?

    你肯定也想过       在OC中相信每一个iOS开发都知道Runtime, 现在Swift也更新到4.0版本了,要是你也学习过Swift的话你可能也会想过这样...

    Mr.RisingSun
  • 2021 iOS底层提升计划

    编程怪才-凌雨画
  • iOS runtime探究(二): 从runtime开始深入理解OC消息转发机制你要知道的runtime都在这里

    你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解...

    WWWWDotPNG
  • RunTime 之消息处理与消息转发

    有关Runtime的知识总结,我本来想集中写成一篇文章的,但是最后发现实在是太长,而且不利于阅读,最后分成了如下几篇:

    進无尽
  • runtime运行时 isa指针 SEL方法选择器 IMP函数指针

    runtime:Objective-C是动态语言,它将很多静态语言在编译和链接时做的事放到了运行时,这个运行时系统就是runtime。

    conanma
  • iOS之Runtime原理解读

    Runtime简介 做过Android开发的同学都知道,早期的Android系统采用的是Dalvik机制,应用每次运行的时候,字节码都需要通过即时编译器转换为机...

    xiangzhihong
  • runtime

    作为iOS开发者,runtime特性是必须了解的重点加分项。这并不是说你可以说出消息机制,运行时消息重定向,或者利用runtime特性实现交换方法等,而是更应该...

    sweet说好的幸福
  • ObjC中的AOP--面向切面编程

    上篇博客我们类比着Java的Spring框架中的依赖注入的实现方式,也试着使用Objective-C来写了一下OC中的依赖注入的实现方式。当然,我们是使用的PL...

    lizelu
  • iOS引用转换:Foundation与Core Foundation对象互相转换(__CFString转NSString,void *转id等等)

    下载地址:苹果公开的源代码在这里可以下载,https://opensource.apple.com/tarballs/

    陈满iOS
  • iOS底层原理总结 - 探寻Runtime本质(一)

    xx_Cc
  • Runtime系列(一)-- 基础知识

    众所周知,Objective-C 是一种运行时语言。运行时怎么来体现的呢?比如一个对象的类型确定,或者对象的方法实现的绑定都是推迟到软件的运行时才能确定的。而运...

    Haley_Wong
  • iOS runtime探究(三): 从runtime开始理解OC的属性property你要知道的runtime都在这里

    你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解...

    WWWWDotPNG
  • 深入浅出 Runtime(一):初识

    对于 NSString *string = [[NSMutableArray alloc]init];

    师大小海腾
  • iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling你要知道的runtime都在这里

    你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解...

    WWWWDotPNG

扫码关注云+社区

领取腾讯云代金券