oc runtime

2021-05-11 14:38:28 浏览数 (1)

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文件里了。

0 人点赞