您好,欢迎访问三七文档
当前位置:首页 > 金融/证券 > 股票报告 > iOS-Runtime从入门到精通
目录CONTENTS01NSObject02Class内部成员03消息转发04自省和消息替换05使用场景01NSObject什么是Runtime?•iOS基于消息机制•iOS运行时才决定要调用哪个方法(动态调用)•Runtime是一个开源库NSObject•NSObject有一部分在Runtime库实现•weak•AutoreleasePool02Class内部结构Class的内部结构:内部成员•Class是一个指向objc_class的结构体指针——所以Class也是一种对象Class的内部结构:内部成员•在Runtime中的定义MetaClassClass的内部结构:内部成员•类的isa成员•objc_allocateClassPair:创建一个类以及MetaClassClass的内部结构:内部成员•方法链表和方法缓存•参数列表•协议列表Class的内部结构:Ivar•Ivar表示类中的实例变量•定义:•Ivar是一个指向objc_ivar的结构体指针,包括了变量名称(ivar_name)、变量类型(ivar_type)等信息Class的内部结构:MetaClass•Class和MetaClass关系图Class的内部结构:SEL•SEL定义:•SEL是一个指向objc_selector的结构体指针,表示方法的签名•不同的类,可以拥有同一个SELClass的内部结构:Method•Method定义:•Class中定义的methodList,保存的就是Method对象的集合performSelector又是什么鬼?•运行时负责查找方法,编译时不做任何校验•使用respondsToSelector预判方法是否存在performSelector语法•同步,线程无关•异步,仅限于主线程•在主线程和子线程都可以执行performSelector语法•调用指定线程中的某个方法•开启子线程在后台运行Class的内部结构:IMP•IMP是implementation的缩写,定义如下:•任何继承自NSObject的类对象,都可以使用id来替代,因为id本身是一个指向objc_object类型的结构体指针Class的内部结构:IMP•IMP是一个函数指针(方法实现地址)•IMP包括以下参数:•id:一个接收消息的对象•SEL:要调用的方法•不定个数的方法参数,可选,从0到,与OC对应的方法参数一致•Block也是一种IMPClass的内部结构:objc_msgSend•定义:•iOS在执行任何方法时都会将其转到这个函数•也具有和IMP一样的参数Class的内部结构:objc_msgSendStudent*小明=[[Studentalloc]init];[小明谈恋爱];[小明抄作业(@”物理”)];调用Student类中的“谈恋爱”方法,就是在Student类的方法链表中查找名为“谈恋爱”的SEL所对应的IMP(方法实现地址),找到了就执行,找不到再想别的办法。上述这些动作是由objc_msgSend函数来完成的,是iOS系统在执行[小明谈恋爱];这个方法时,将其自动转到objc_msgSend函数的。Class的内部结构:方法缓存•objc_msgSend函数每次都要在类的方法列表中根据SEL去查找IMP•为了提高查找速度,设计出方法缓存•如果当前类的方法缓存和链表中都找不到,就去它的父类寻找,找到则加入当前类的缓存中03消息转发消息转发•如果objc_msgSend找不到怎么办?--抛出unrecognizedselectorsenttoxxx异常•补救措施(按顺序执行):•MethodResolution•FastForwarding•NormalForwarding消息转发:流程图消息转发:消息转发之MethodResolution•在要调用的方法所在的类增加resolveInstanceMethod方法,让别的方法去处理:消息转发:消息转发之FastForwarding•在要调用的方法所在的类增加forwardingTargetForSelector方法,移花接木,让别的类去处理:消息转发:消息转发之NormalForwarding•在要调用的方法所在的类增加forwardInvocation和methodSignatureForSelector方法,移花接木,让别的类去处理:三种转发机制的比较•MethodResolution:在自己及父类中寻找•FastForwarding:在别的类寻找•NormalForwarding:与消息相关的所有信息都封装在NSInvocation对象中,包括SEL、方法参数等NormalForwarding中的v@:•第一个参数v,表示返回类型,v表示void•第二个参数@,表示id,固定值•第三个参数:,表示SEL,固定值•如果还有第4个甚至更多的字符,那就是代表SEL所对应的方法参数了,一般都对应@,即NSObjectNormalForwarding中的v@:符号代表类型*char*^typetype*@NSObject*或id^@NSError**#NSObjectvvoid:SEL消息转发的最后一步(第四步):doesNotRecognizeSelector•doesNotRecognizeSelector由系统提供•负责抛出异常用消息转发实现多重继承•在Parent类定义eat方法,但是不实现•在Child类定义并实现eat方法•在Parent类使用forwardingTargetForSelector方法04自省、消息替换和关联对象概述•iOSRuntime=自省+方法替换•自省:获取信息的函数•方法替换:修改或新增方法的函数自省(introspective)•自省是对象的固有能力,即程序运行时,对象可根据一些方法,获取自身的信息,或动态执行一些方法•我是谁?自省(introspective)方法名称作用class返回对象的类isKindOfClass检查对象是否在指定的类继承体系中isMemberOfClass检查对象是否在指定的类继承体系中respondsoSelector检查对象能否相应指定的消息conformsToProtocol检查对象是否实现了指定协议类的方法methodForSelector返回指定方法实现的地址performSelector:withObject执行SEL所指代的方法•NSObject提供的自省方法:自省(introspective)•object_getClass和object_getClassName:取得任意一个对象的类和类名多用于判断类型自省(introspective)•class_copyPropertyList:获取类的所有属性列表,得到一个数组•property_getName:获取到某个属性的名称自省(introspective)•class_copyMethodList:获取类的所有方法列表,得到一个数组•method_getName:获取到每个方法对应的SEL•类似的,关于获取Ivar的方法自省(introspective)•带有From文字的方法:•NSClassFromString:反射•可用于导航器•可用于判断某个class是否存在•NSSelectorFromString:从字符串中反射得到Selector类型:方法替换(MethodSwizzing)•object_setClass用于把一个对象设置为一个新的类型方法替换(MethodSwizzing)•load和initialize方法用于类的加载和初始化,是一开始就执行的方法方法替换(MethodSwizzing)•objc_allocateClassPair用于动态创建一个新类同时还创建了新类的MetaClass指定新类继承自NSObject方法替换(MethodSwizzing)•class_addMethod为一个类增加新的方法为ClassA新增一个方法doSomething,指定它的实现(IMP)是newMethod方法替换(MethodSwizzing)•class_addMethod为一个类增加新的方法,带参数的实现为ClassA新增一个方法doSomething,指定它的实现(IMP)是newMethod方法替换(MethodSwizzing)•method_setImplementation为类的某个原有方法Method设置一个新的IMP实现把Person的sayHello方法实现替换为sayHi方法实现方法替换(MethodSwizzing)•class_replaceMethod•把一个类的某个方法,替换为另一个方法•是method_setImplementation和class_addMethod这两种场景的组合•1)旧的方法SELname如果不存在,那其实就是调用class_AddMethod方法,这时候types参数就是非常有用的了。•2)旧的方法SELname如果存在,那其实就是调用method_setImplementation方法方法替换(MethodSwizzing)•class_replaceMethod的例子:把Person的sayHello方法实现替换为sayHi方法实现方法替换(MethodSwizzing)•method_exchangeImplementations交换两个方法的实现关联对象:为一个类增加新方法或属性•使用Category:缺点是不能增加属性•使用关联对象:把两个对象关联起来•objc_setAssociatedObject•objc_getAssociatedObject•objc_removeAssociatedObjects:很少使用•分为静态和动态两种方式05使用场景使用场景:AOP•面向切面编程•日志记录•性能统计•安全控制•事务处理•异常处理使用场景:AOPAOP的优势:•减少切面业务的开发量•减少代码耦合,方便复用•提高代码review的质量使用场景:减少机械性的if判断?使用场景:写日志使用场景:Aspects•提供的方法使用场景:Aspects•写入配置文件使用场景:Aspects•读取配置文件使用场景:NSProxy•NSProxy也是一个根类,类似于NSObject•NSProxy是一个抽象类,实现了NSObject协议•NSProxy是一种高级的代理,通过Runtime的消息转发机制代理模式的实现•静态代理•NSProxy继承NSProxy-delegate提供消息转发机制-methodSignatureForSelector-forwardInvocation定义两个代理方法-helloWorld-goodbye使用场景:PV和UV•截获UIWindow的sendEventHooked方法,所有触摸事件都经过UIWindow使用场景:热修复•WaxPatch•JSPatch使用场景:避免按钮重复点击•第一种解决方案:使用sender参数使用场景:避免按钮重复点击•第二种解决方案:使用GCD延迟使用场景:避免按钮重复点击•第三种解决方案:SwizzingTHANKYOU!
本文标题:iOS-Runtime从入门到精通
链接地址:https://www.777doc.com/doc-6377586 .html