iOS Objc Runtime 教程+实例Demo.docx
《iOS Objc Runtime 教程+实例Demo.docx》由会员分享,可在线阅读,更多相关《iOS Objc Runtime 教程+实例Demo.docx(26页珍藏版)》请在冰点文库上搜索。
![iOS Objc Runtime 教程+实例Demo.docx](https://file1.bingdoc.com/fileroot1/2023-5/15/5618c5f1-b84f-4fd2-be3f-115f34ceaa30/5618c5f1-b84f-4fd2-be3f-115f34ceaa301.gif)
iOSObjcRuntime教程+实例Demo
iOSObjcRuntime教程+实例Demo
应用场景
将某些OC代码转为运行时代码,探究底层,比如block的实现原理
拦截系统自带的方法调用(Swizzle黑魔法),比如拦截imageNamed:
、viewDidLoad、alloc
实现分类也可以增加属性
实现NSCoding的自动归档和自动解档
实现字典和模型的自动转换。
(MJExtension)
修BUG神器,如果大型框架的BUG通过Runtime来解决,非常好用。
一些常用类型
Method
Method
Anopaquetypethatrepresentsamethodinaclassdefinition.
Declaration
typedefstructobjc_method*Method;
代表类定义中的方法的不透明类型。
Class
Class
AnopaquetypethatrepresentsanObjective-Cclass.
Declaration
typedefstructobjc_class*Class;
代表Objective-C中的类
Ivar
Anopaquetypethatrepresentsaninstancevariable.
Declaration
typedefstructobjc_ivar*Ivar;
代表实例变量
IMP
IMP
Apointertothestartofamethodimplementation.
指向方法实现的开始的内存地址的指针。
SEL
SEL
Definesanopaquetypethatrepresentsamethodselector.
Declaration
typedefstructobjc_selector*SEL;
代表方法的选择器
类与对象操作函数
runtime有很多的函数可以操作类和对象。
类相关的是class为前缀,对象相关操作是objc或object_为前缀。
类相关操作函数
name
//获取类的类名
constchar*class_getName(Classcls);
super_class和meta-class
//获取类的父类
Classclass_getSuperclass(Classcls);
//判断给定的Class是否是一个metaclass
BOOLclass_isMetaClass(Classcls);
instance_size
//获取实例大小
size_tclass_getInstanceSize(Classcls);
成员变量(ivars)及属性
//成员变量操作函数
//获取类中指定名称实例成员变量的信息
Ivarclass_getInstanceVariable(Classcls,constchar*name);
//获取类成员变量的信息
Ivarclass_getClassVariable(Classcls,constchar*name);
//添加成员变量
BOOLclass_addIvar(Classcls,constchar*name,size_tsize,uint8_talignment,constchar*types);//这个只能够向在runtime时创建的类添加成员变量
//获取整个成员变量列表
Ivar*class_copyIvarList(Classcls,unsignedint*outCount);//必须使用free()来释放这个数组
//属性操作函数
//获取类中指定名称实例成员变量的信息
Ivarclass_getInstanceVariable(Classcls,constchar*name);
//获取类成员变量的信息
Ivarclass_getClassVariable(Classcls,constchar*name);
//添加成员变量
BOOLclass_addIvar(Classcls,constchar*name,size_tsize,uint8_talignment,constchar*types);
//获取整个成员变量列表
Ivar*class_copyIvarList(Classcls,unsignedint*outCount);
methodLists
//添加方法
BOOLclass_addMethod(Classcls,SELname,IMPimp,constchar*types);//和成员变量不同的是可以为类动态添加方法。
如果有同名会返回NO,修改的话需要使用method_setImplementation
//获取实例方法
Methodclass_getInstanceMethod(Classcls,SELname);
//获取类方法
Methodclass_getClassMethod(Classcls,SELname);
//获取所有方法的数组
Method*class_copyMethodList(Classcls,unsignedint*outCount);
//替代方法的实现
IMPclass_replaceMethod(Classcls,SELname,IMPimp,constchar*types);
//返回方法的具体实现
IMPclass_getMethodImplementation(Classcls,SELname);
IMPclass_getMethodImplementation_stret(Classcls,SELname);
//类实例是否响应指定的selector
BOOLclass_respondsToSelector(Classcls,SELsel);
objc_protocol_list
//添加协议
BOOLclass_addProtocol(Classcls,Protocol*protocol);
//返回类是否实现指定的协议
BOOLclass_conformsToProtocol(Classcls,Protocol*protocol);
//返回类实现的协议列表
Protocol*class_copyProtocolList(Classcls,unsignedint*outCount);
version
//获取版本号
intclass_getVersion(Classcls);
//设置版本号
voidclass_setVersion(Classcls,intversion);
实例
//-----------------------------------------------------------
//MyClass.h
@interfaceMyClass:
NSObject
@property(nonatomic,strong)NSArray*array;
@property(nonatomic,copy)NSString*string;
-(void)method1;
-(void)method2;
+(void)classMethod1;
@end
//-----------------------------------------------------------
//MyClass.m
#import"MyClass.h"
@interfaceMyClass(){
NSInteger_instance1;
NSString*_instance2;
}
@property(nonatomic,assign)NSUIntegerinteger;
-(void)method3WithArg1:
(NSInteger)arg1arg2:
(NSString*)arg2;
@end
@implementationMyClass
+(void)classMethod1{
}
-(void)method1{
NSLog(@"callmethodmethod1");
}
-(void)method2{
}
-(void)method3WithArg1:
(NSInteger)arg1arg2:
(NSString*)arg2{
NSLog(@"arg1:
%ld,arg2:
%@",arg1,arg2);
}
@end
//-----------------------------------------------------------
//main.h
#import"MyClass.h"
#import"MySubClass.h"
#import
intmain(intargc,constchar*argv[]){
@autoreleasepool{
MyClass*myClass=[[MyClassalloc]init];
unsignedintoutCount=0;
Classcls=myClass.class;
//类名
NSLog(@"classname:
%s",class_getName(cls));
NSLog(@"==========================================================");
//父类
NSLog(@"superclassname:
%s",class_getName(class_getSuperclass(cls)));
NSLog(@"==========================================================");
//是否是元类
NSLog(@"MyClassis%@ameta-class",(class_isMetaClass(cls)?
@"":
@"not"));
NSLog(@"==========================================================");
Classmeta_class=objc_getMetaClass(class_getName(cls));
NSLog(@"%s'smeta-classis%s",class_getName(cls),class_getName(meta_class));
NSLog(@"==========================================================");
//变量实例大小
NSLog(@"instancesize:
%zu",class_getInstanceSize(cls));
NSLog(@"==========================================================");
//成员变量
Ivar*ivars=class_copyIvarList(cls,&outCount);
for(inti=0;iIvarivar=ivars[i];
NSLog(@"instancevariable'sname:
%satindex:
%d",ivar_getName(ivar),i);
}
free(ivars);
Ivarstring=class_getInstanceVariable(cls,"_string");
if(string!
=NULL){
NSLog(@"instacevariable%s",ivar_getName(string));
}
NSLog(@"==========================================================");
//属性操作
objc_property_t*properties=class_copyPropertyList(cls,&outCount);
for(inti=0;iobjc_property_tproperty=properties[i];
NSLog(@"property'sname:
%s",property_getName(property));
}
free(properties);
objc_property_tarray=class_getProperty(cls,"array");
if(array!
=NULL){
NSLog(@"property%s",property_getName(array));
}
NSLog(@"==========================================================");
//方法操作
Method*methods=class_copyMethodList(cls,&outCount);
for(inti=0;iMethodmethod=methods[i];
NSLog(@"method'ssignature:
%s",method_getName(method));
}
free(methods);
Methodmethod1=class_getInstanceMethod(cls,@selector(method1));
if(method1!
=NULL){
NSLog(@"method%s",method_getName(method1));
}
MethodclassMethod=class_getClassMethod(cls,@selector(classMethod1));
if(classMethod!
=NULL){
NSLog(@"classmethod:
%s",method_getName(classMethod));
}
NSLog(@"MyClassis%@responsdtoselector:
method3WithArg1:
arg2:
",class_respondsToSelector(cls,@selector(method3WithArg1:
arg2:
))?
@"":
@"not");
IMPimp=class_getMethodImplementation(cls,@selector(method1));
imp();
NSLog(@"==========================================================");
//协议
Protocol*__unsafe_unretained*protocols=class_copyProtocolList(cls,&outCount);
Protocol*protocol;
for(inti=0;iprotocol=protocols[i];
NSLog(@"protocolname:
%s",protocol_getName(protocol));
}
NSLog(@"MyClassis%@responsedtoprotocol%s",class_conformsToProtocol(cls,protocol)?
@"":
@"not",protocol_getName(protocol));
NSLog(@"==========================================================");
}
return0;
}
动态创建类和对象
动态创建类
//创建一个新类和元类
Classobjc_allocateClassPair(Classsuperclass,constchar*name,size_textraBytes);//如果创建的是rootclass,则superclass为Nil。
extraBytes通常为0
//销毁一个类及其相关联的类
voidobjc_disposeClassPair(Classcls);//在运行中还存在或存在子类实例,就不能够调用这个。
//在应用中注册由objc_allocateClassPair创建的类
voidobjc_registerClassPair(Classcls);//创建了新类后,然后使用class_addMethod,class_addIvar函数为新类添加方法,实例变量和属性后再调用这个来注册类,再之后就能够用了。
使用实例
Classcls=objc_allocateClassPair(MyClass.class,"MySubClass",0);
class_addMethod(cls,@selector(submethod1),(IMP)imp_submethod1,"v@:
");
class_replaceMethod(cls,@selector(method1),(IMP)imp_submethod1,"v@:
");
class_addIvar(cls,"_ivar1",sizeof(NSString*),log(sizeof(NSString*)),"i");
objc_property_attribute_ttype={"T","@\"NSString\""};
objc_property_attribute_townership={"C",""};
objc_property_attribute_tbackingivar={"V","_ivar1"};
objc_property_attribute_tattrs[]={type,ownership,backingivar};
class_addProperty(cls,"property2",attrs,3);
objc_registerClassPair(cls);
idinstance=[[clsalloc]init];
[instanceperformSelector:
@selector(submethod1)];
[instanceperformSelector:
@selector(method1)];
动态创建对象
//创建类实例
idclass_createInstance(Classcls,size_textraBytes);//会在heap里给类分配内存。
这个方法和+alloc方法类似。
//在指定位置创建类实例
idobjc_constructInstance(Classcls,void*bytes);
//销毁类实例
void*objc_destructInstance(idobj);//不会释放移除任何相关引用
测试下效果
//可以看出class_createInstance和alloc的不同
idtheObject=class_createInstance(NSString.class,sizeof(unsigned));
idstr1=[theObjectinit];
NSLog(@"%@",[str1class]);
idstr2=[[NSStringalloc]initWithString:
@"test"];
NSLog(@"%@",[str2class]);
实例操作函数
这些函数是针对创建的实例对象的一系列操作函数。
整个对象操作的函数
//返回指定对象的一份拷贝
idobject_copy(idobj,size_tsize);
//释放指定对象占用的内存
idobject_dispose(idobj);
应用场景
//把a转换成占用更多空间的子类b
NSObject*a=[[NSObjectalloc]init];
idnewB=object_copy(a,class_getInstanceSize(MyClass.class));
object_setClass(newB,MyClass.class);
object_dispose(a);
对象实例变量进行操作的函数
//修改类实例的实例变量的值
Ivarobject_setInstanceVariable(idobj,constchar*name,void*value);
//获取对象实例变量的值
Ivarobject_getInstanceVariable(idobj,constchar*name,void**outValue);
//返回指向给定对象分配的任何额外字节的指针
void*object_getIndexedIvars(idobj);
//返回对象中实例变量的值
idobject_getIvar(idobj,Ivarivar);
//设置对象中实例变量的值
voidobject_setIvar(idobj,Ivarivar,idvalue);
对对象类操作
//返回给定对象的类名
constchar*object_getClassName(idobj);
//返回对象的类
Classobject_getClass(idobj);
//设置对象的类
Classobject_setClass(idobj,Classcls);
获取类定义
//获取已注册的类定义的列表
intobjc_getClassList(Class*buffer,intbufferCount);
//创建并返回一个指向所有已注册类的指针列表
Class*objc_copyClassList(unsignedint