Cocoa touch Cocoa:iAction回调是同步的还是异步的?

Cocoa touch Cocoa:iAction回调是同步的还是异步的?,cocoa-touch,cocoa,Cocoa Touch,Cocoa,假设我用xib文件中的按钮连接iAction。当应用程序运行时,我点击按钮,动作是同步调用还是将performSelector请求置于runloop上?它是同步的 在iOS应用程序中,回溯看起来像: frame #0: 0x000025d2 MyApp`-[ViewController myAction:] + 34 at ViewController.m:31 frame #1: 0x010e2705 libobjc.A.dylib`-[NSObject performSelector:wit

假设我用xib文件中的按钮连接iAction。当应用程序运行时,我点击按钮,动作是同步调用还是将performSelector请求置于runloop上?

它是同步的

在iOS应用程序中,回溯看起来像:

frame #0: 0x000025d2 MyApp`-[ViewController myAction:] + 34 at ViewController.m:31
frame #1: 0x010e2705 libobjc.A.dylib`-[NSObject performSelector:withObject:withObject:] + 77
frame #2: 0x00019920 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 96
frame #3: 0x000198b8 UIKit`-[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
frame #4: 0x000da671 UIKit`-[UIControl sendAction:to:forEvent:] + 66
frame #5: 0x000dabcf UIKit`-[UIControl(Internal) _sendActionsForEvents:withEvent:] + 578
frame #6: 0x000d9d38 UIKit`-[UIControl touchesEnded:withEvent:] + 546
frame #7: 0x0004933f UIKit`-[UIWindow _sendTouchesForEvent:] + 846
frame #8: 0x00049552 UIKit`-[UIWindow sendEvent:] + 273
frame #9: 0x000273aa UIKit`-[UIApplication sendEvent:] + 436
frame #10: 0x00018cf8 UIKit`_UIApplicationHandleEvent + 9874
frame #11: 0x01becdf9 GraphicsServices`_PurpleEventCallback + 339
frame #12: 0x01becad0 GraphicsServices`PurpleEventCallback + 46
frame #13: 0x01c06bf5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
frame #14: 0x01c06962 CoreFoundation`__CFRunLoopDoSource1 + 146
frame #15: 0x01c37bb6 CoreFoundation`__CFRunLoopRun + 2118
frame #16: 0x01c36f44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #17: 0x01c36e1b CoreFoundation`CFRunLoopRunInMode + 123
frame #18: 0x01beb7e3 GraphicsServices`GSEventRunModal + 88
frame #19: 0x01beb668 GraphicsServices`GSEventRun + 104
frame #20: 0x0001665c UIKit`UIApplicationMain + 1211
frame #21: 0x00001f62 MyApp`main + 130 at main.m:16
frame #22: 0x00001e95 MyApp`start + 53
这是直接同步代码。应用程序接收到一个触控结束事件,找出将其发送到哪里(按钮),并向按钮的目标发送一条消息

相反,通过
-[NSObject performSelector:withObject:afterDelay:
异步调用的方法具有如下回溯:

frame #0: 0x00002628 MyApp`-[ViewController myAsyncAction:] + 24 at ViewController.m:37
frame #1: 0x00acce83 Foundation`__NSFireDelayedPerform + 380
frame #2: 0x01c50376 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
frame #3: 0x01c4fe06 CoreFoundation`__CFRunLoopDoTimer + 534
frame #4: 0x01c37a82 CoreFoundation`__CFRunLoopRun + 1810
frame #5: 0x01c36f44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #6: 0x01c36e1b CoreFoundation`CFRunLoopRunInMode + 123
frame #7: 0x01beb7e3 GraphicsServices`GSEventRunModal + 88
frame #8: 0x01beb668 GraphicsServices`GSEventRun + 104
frame #9: 0x0001665c UIKit`UIApplicationMain + 1211
frame #10: 0x00001f62 MyApp`main + 130 at main.m:16
frame #11: 0x00001e95 MyApp`start + 53

您可以清楚地看到计时器触发并调用其回调,在此基础上构建的“延迟执行”将被触发。

在操作中设置断点。点击按钮,然后查看backtrace中调用操作的方法。它看起来像是由该代码同步调用的,还是像是由延迟的performSelector调用的?@KurtRevis我认为它是异步的,也是“看起来”异步的,我只是想确定一下,所以我在这里问。谢谢,但我认为performSelector是异步的,不管它是否有延迟参数。performSelector是由runloop获取的,不是CPU上的直接跳转指令,这就是我所说的异步,也许我们有一些误解。您所说的确切的performSelector方法是什么
-[NSObject performSelector://code>和带有一个或两个
对象
参数的变量同步发生,而不经过运行循环<代码>-[NSObject performSelector:withObject:afterDelay:
异步发生(由运行循环触发)。非常感谢您,我终于理解了这一点。performSelector在NSObject协议中定义,performSelector:afterDelay在NSObject类中。还要注意,事件处理本身是异步的,依赖于runloop。事实上,我的问题是这样的,假设我有两个按钮,其中一个连接到iAction,我希望这样:当用户点击一个按钮时,禁用另一个按钮。当用户点击过快,以至于在runloop处理第一个点击事件之前,会生成第二个点击事件。因此,简单地在iAction中设置另一个按钮的enabled属性并不是完全安全的,特别是当iAction中有大量工作并且每次运行都会花费很长时间时。我现在使用ivar作为mutax来解决这个问题。很抱歉,我在开始时没有把问题说清楚。