—— iOS 运行时中方法的调用流程

—— iOS 运行时中方法的调用流程,第1张

在iOS运行时系统中,调用方法的本质就是利用objc_msgSend进行消息发送:

iOS 中所有的类都是继承于 NSObject,一个对象所具有的方法分为实例方法和类方法,编译完成后的对象中,存在一个实例方法链表、一个缓存方法链表。当实例调用方法经objc_msgSend时:首先,在相应 *** 做的对象中的缓存方法列表中找调用的方法,若找到,转向相应的实现并执行;若没找到,在对象的方法列表中查找,若是找到,转向相应的实现并执行;若是没找到,则递归的去父类指针所指向的类对象方法列表中查找;以此类推,若是一直到根类都没有找到,转向拦截调用,走消息转发机制;若是没有重写拦截调用方法,程序报错;

消息转发也被称为拦截调用,就是在找不到调用的方法后,且在程序崩溃以前,有机会经过重写NSObject的四个方法来补救处理:

若以上都不中,调用 NSObject 的 doesNotRecognizeSelector 方法抛出异常:

利用以上机制,可以对resolveInstanceMethod 和 resolveClassMethod 两个方法进行方法交换,拦截可能出现的 iOS 崩溃,然后自定义处理。

消息转发机制依次的三个过程:1)动态方法解析;2)转发给其他备用的接收对象;3)消息所有相关内容封装成一个NSInvocation对象,再做最后的尝试。

第一阶段,先征询接收者所属的类,是否需要动态的添加方法,用来处理当前未找到的方法。对象在无法解读消息时会首先调用所属类的下列类方法,来判断是否能接收消息:

例:

第二阶段,如果动态方法解析没有发现添加的方法,那么尝试转发给其他对象来处理这个方法。该步骤调用的方法是:

例:

第三阶段,如果没有可用的备选者,那么系统就会把消息所有相关内容封装成一个NSInvocation对象,再做最后的尝试,启动完整的消息转发。先调用methodSignatureForSelector:获取方法签名,然后再调用forwardInvocation:进行处理,这一步的处理可以直接转发给其它对象,即和第二步的效果等效,但是很少有人这么干,因为消息处理越靠后,就表示处理消息的成本越大,性能的开销就越大。所以,在这种方式下,一般会改变消息内容,比如增加参数,改变选择子等等,具体根据实际情况而定。

例:

这里就是利用了消息转发机制的第三个阶段,将NSIvocation分发给多个代理去响应。

https://blog.csdn.net/kingjxust/article/details/49559091

http://blog.cnbang.net/tech/2808/

http://blog.cnbang.net/tech/2855/

由于OC的动态特性,在编译过程向类发送了其无法理解的消息并不会报错,因为在运行时,我们可以改变对象调用的方法、向类中添加方法。只有当程序运行起来之后,才知道要真正执行哪个函数(动态绑定)。

OC消息发送原理、方法查找过程:

简单理解:

OC、运行时初始化时机:

https://www.jianshu.com/p/4b93b40977b5

https://blog.csdn.net/weixin_30920513/article/details/100093380

参考文章:

https://www.jianshu.com/p/7e132cda35cd

https://www.cnblogs.com/feng9exe/p/10397102.html

https://www.shangmayuan.com/a/02d9b8b219b24d888ef93b97.html

https://blog.csdn.net/lin1109221208/article/details/108724965

iOS之使用NSInvocation调用方法

https://www.jianshu.com/p/e24b3420f1b4

一,

调用自己开发的应用

1)在plist文件中,注册对外接口

在xcode

group&files 里面,展开 resources选择info.plist

鼠标右击information

property list ,然后从列表中选择URL types

右击

add row 添加一个对象(item)右击item add row

从列表中选择

URL  Schemes 再右击添加一个对象(item1)

将item1得值设置为:myapp

这个myapp就是对外接口,其它应用可以通过它,调用该应用

plist如下图所示:

2).处理URL请求

应用程序委托在 application:handleOpenURL:方法中处理传递给应用程序的URL请求。如果您已经为自己

     的应用程序注册了定制的URL模式,则务必在委托中实现这个方法。

下面代码实现了这个委托方法;

-

(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL

*)url

{

if([[url

scheme] isEqualToString:@"myapp"]){

[application

setApplicationIconBadgeNumber:10]

return

YES

}

return

NO

}

3).测试外部调用

1.回到Home屏幕,启动Safari(在iPhone仿真器上,在菜单上选择Hardware->Home命令就可以回到Home屏幕)。

2.在Safari的地址栏中,键入使用定制模式的URL: myapp:

3.确认您的应用程序是否启动,以及应用程序委托是否收到application:handleOpenURL:消息。

4)调用方法

在你需要调用上面注册过对外接口的应用中,添加下面代码即可

NSURL

*url = [NSURL URLWithString:@"myapp:"]

[[UIApplication

sharedApplication] openURL:url]

通过上述两个步骤,你可以在你的应用中,让用户打开你的其它应用

二,

调用IOS自带的应用

上面讲述的是调用自身的应用,讲解了如何在自己应用之间调用问题,今天介绍一下如果调用IOS自带的app的方法

一、调用app

store界面方法

在实际开发中,往往要推荐自己其他应用和推荐自己的收费软件,那么我们就需要在程序中直接连接到app

store的相应页面。

实际上的做法很简单,使用的还是UIApplication类的OpenURL方法:

[[UIApplication

sharedApplication] openURL:[NSURL URLWithString:@"程序的相应连接"]]

二、调用其它应用的方法


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12202333.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存