gpt4 book ai didi

ios - [UIApplication sendEvent:]是否在NSRunLoop中执行?

转载 作者:可可西里 更新时间:2023-11-01 06:20:07 30 4
gpt4 key购买 nike

我读了这个apple doc about runloop:

运行循环是事件处理循环,可用于安排工作并协调传入事件的接收...运行循环从两种不同类型的源接收事件。输入源传递异步事件...计时器源传递同步事件...

现在我知道performSelector:withObject:afterDelay:NSTimer在运行循环中运行。

该文档没有提及触摸事件作为输入源。我想知道:

Q1:[UIApplication sendEvent:]发送的触摸事件是否也在某些默认运行循环中运行?
问题2:如果问题1的答案为“是”,则默认运行循环是否与处理performSelector:withObject:afterDelay:NSTimer事件的运行循环相同?

最佳答案

我不会仅凭我的猜测就假装答案的准确性。

我将在此答案中涵盖的内容:

  • 马赫IPC / RPC。 (进程间通信/远程过程调用)
  • 紫色项目。 (iOS代号)
  • GraphicsServices。 (私有框架)
  • 跳板。 (iOS GUI应用)
  • Runloop本身。 (这是所有这些的角色)


  • 我对mach并不是很熟悉,(我计划在将来对它进行更深入的了解),但是我知道运行mach内核的基本原语。 Mach内核通过发送 消息来使用 端口进程之间进行通信。您可以将流程视为您的应用程序。

    项目紫色是iOS的简单代号。为什么我要提这个?因为有一个mach'Purple system event'端口,用于发送 SpringBoard 应用程序的系统事件。

    据我所知,有私有的 GraphicsServices框架,它具有:
  • 检查设备功能。 (相机,蓝牙,GPS等)
  • 获取屏幕尺寸/尺寸,方向
  • 呈现/隐藏/管理键盘
  • 当然是发送事件(触摸,音量设置,静音振铃开关,设备锁定等)

  • GraphicServices框架正在使用“紫色系统事件”端口发送所有事件。

    如果您感兴趣,可以在此处查看其标题:

    https://github.com/rpetrich/iphoneheaders/tree/master/GraphicsServices

    iOS具有名为SpringBoard的应用程序,该应用程序是用户在其iPhone / iPad / iPod上浏览时看到的内容,它负责启动应用程序,向他们发送事件,接收来自它们的通知等。而且我认为您已经猜到了SpringBoard从Purple系统事件端口接收事件,并且几乎所有事件都传递给了 Activity 应用程序。 (有些事件仅与SpringBoard相关,例如设备锁定。)

    有关SpringBoard的更多信息,请查看:

    http://theiphonewiki.com/wiki//System/Library/CoreServices/SpringBoard.app

    现在, runloop 在所有这些角色中起什么作用?如果查看 CFRunloopRef的源代码,您会发现它与mach端口紧密配合。 (可以在 https://www.opensource.apple.com/source/CF/CF-476.10/CFRunLoop.c上找到源代码)

    当您调用CFRunLoopRun时,它仅等待来自端口的消息。

    在给定的屏幕截图上,您可以看到 UIApplicationMain函数调用GraphicServices框架无限循环以模态运行并通过进入trap: mach_msg的调用 mach_msg_trap等待事件。它使线程进入睡眠状态,并在新事件到达时唤醒。我还看到了 UIKit ,它为SpringBoard 传递的事件注册了自己的回调。稍后我们将在事件到达时在堆栈跟踪 PurpleEventCallback_PurpleEventCallback函数调用中看到。此功能充当所有GraphicServices和UIKit内容之间的桥梁。 (我的意思是,我们收到了由UIKit包装在UIEvent中的GSEvent等)。您可以看到函数名称是“Project Purple”代号的复活节彩蛋。

    至于 UIKit ,我假设它注册了自己的 CFRunloopSourceRef,它会调用 _UIApplicationHandleEventQueue函数并处理诸如触摸等操作。 (将它们委派给您的应用程序)请参见屏幕截图(系统如何处理触摸):

    当应用程序挂起时- UIKit 使此源无效。看截图。 (我已经在 CFRunLoopRemoveSource上设置了符号断点,并且您可以在堆栈跟踪中看到UIKit准备挂起应用程序。)然后,我选择 CFRunLoopSourceInvalidate框架来查找此运行循环源是否与马赫码相关。 CFRunLoopSourceInvalidate方法具有以下原型:
    void CFRunLoopSourceInvalidate (
    CFRunLoopSourceRef source
    );

    因此,使用lldb并知道参数应在方法调用时存储在寄存器中后,我打印出了寄存器值并读取了与mach东西相关的建议参数。如您所见-是的。



    UIKit 还通知成功启动,成功暂停等。通知谁? 跳板。有一种特定的方法用于发送特定机器端口的事件,称为 GSSendEvent()。传递的端口是应用程序的事件端口。有关更多信息,请参见:

    http://iphonedevwiki.net/index.php/GSEvent

    还有一些屏幕快照展示了这种交流:

    应用程序完成了启动并将其报告回 SpringBoard :

    应用程序收到事件,您可以看到它正在做一些内部事情,设置状态栏,从情节提要中实例化视图控制器,返回报告等:

    暂停应用程序调用堆栈:

    摘要:

    GraphicServices 使用“紫色系统事件”端口发送与触摸,设备锁定,挂起 Activity 应用程序等有关的事件。
    SpringBoard 从“紫色系统事件”端口接收消息,并通过获取其事件端口将其发送到 Activity 应用程序。 UIKit 接收它们,处理它们,然后可以使用 SpringBoard 事件端口将结果发送回 SpringBoard

    关于ios - [UIApplication sendEvent:]是否在NSRunLoop中执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22116698/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com