Githawk: Reaction context menu opening time

Created on 15 Aug 2018  Ā·  14Comments  Ā·  Source: GitHawkApp/GitHawk

For me I’d personally like it to open a bit quicker. It’s just slow enough that I’m not sure i hit the button each time I tap the smiley 😃

Sent with GitHawk

šŸ› bug šŸŽØ design

Most helpful comment

@BrianLitwin subclasses UIApplication and overrode sendEvent(). Set a global Date every time that’s called. Then in button action I print timeIntervalSinceNow.

Sent with GitHawk

All 14 comments

If it was the same speed as the manager button that would be good

Sent with GitHawk

Hmph, you're right it does feel clunky. It's the same code! Something is definitely off.

I was gonna check the code before I made that statement but then I didn’t. 😊. Prob should have.

Sent with GitHawk

This has to be something with scroll views delaying content touches.

Sent with GitHawk

Classic scrollview causing issues again.

I shouldn’t have read this :(

Sent with GitHawk

@BasThomas I know, cannot unsee

Sent with GitHawk

Whoops 😬 lol

Sent with GitHawk

Did some debugging to track time between a UIEvent being sent and the .touchUpInside action actually being executed. Found some interesting stack traces. The numbers at the beginning are a print of the time (in negative seconds) taken between UIApplication.sendEvent() and the button action handling in the cell.

Slow response time

-0.351912021636963
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
  * frame #0: 0x0000000100663448 Freetime`IssueCommentReactionCell.onAddButton(sender=0x000000014fc56f30, self=0x000000014fc55630) at IssueCommentReactionCell.swift:116
    frame #1: 0x00000001006635b0 Freetime`@objc IssueCommentReactionCell.onAddButton(sender:) at IssueCommentReactionCell.swift:0
    frame #2: 0x000000018c6d164c UIKit`-[UIApplication sendAction:to:from:forEvent:] + 96
    frame #3: 0x00000001007310ec Freetime`Application.sendAction(action="onAddButtonWithSender:", target=some, sender=some, event=0x00000001cc11b090, self=0x0000000147f017c0) at Application.swift:21
    frame #4: 0x0000000100731334 Freetime`@objc Application.sendAction(_:to:from:for:) at Application.swift:0
    frame #5: 0x000000018c7f2870 UIKit`-[UIControl sendAction:to:forEvent:] + 80
    frame #6: 0x000000018c6d7700 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 440
    frame #7: 0x000000018c80d1a8 UIKit`-[UIControl touchesEnded:withEvent:] + 572
    frame #8: 0x000000018ccb2ee8 UIKit`_UIGestureEnvironmentSortAndSendDelayedTouches + 4340
    frame #9: 0x000000018ccafc60 UIKit`_UIGestureEnvironmentUpdate + 1236
    frame #10: 0x000000018290a910 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
    frame #11: 0x0000000182908238 CoreFoundation`__CFRunLoopDoObservers + 412
    frame #12: 0x0000000182908884 CoreFoundation`__CFRunLoopRun + 1436
    frame #13: 0x0000000182828da8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #14: 0x000000018480e020 GraphicsServices`GSEventRunModal + 100
    frame #15: 0x000000018c848758 UIKit`UIApplicationMain + 236
    frame #16: 0x00000001003153f0 Freetime`main at main.swift:11
    frame #17: 0x00000001822b9fc0 libdyld.dylib`start + 4
(lldb) 

Fast response time

-0.0017249584197998
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
  * frame #0: 0x0000000100663448 Freetime`IssueCommentReactionCell.onAddButton(sender=0x0000000147f62e90, self=0x0000000147f637a0) at IssueCommentReactionCell.swift:116
    frame #1: 0x00000001006635b0 Freetime`@objc IssueCommentReactionCell.onAddButton(sender:) at IssueCommentReactionCell.swift:0
    frame #2: 0x000000018c6d164c UIKit`-[UIApplication sendAction:to:from:forEvent:] + 96
    frame #3: 0x00000001007310ec Freetime`Application.sendAction(action="onAddButtonWithSender:", target=some, sender=some, event=0x00000001c011be10, self=0x0000000147f017c0) at Application.swift:21
    frame #4: 0x0000000100731334 Freetime`@objc Application.sendAction(_:to:from:for:) at Application.swift:0
    frame #5: 0x000000018c7f2870 UIKit`-[UIControl sendAction:to:forEvent:] + 80
    frame #6: 0x000000018c6d7700 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 440
    frame #7: 0x000000018c80d1a8 UIKit`-[UIControl touchesEnded:withEvent:] + 572
    frame #8: 0x000000018ccb2ee8 UIKit`_UIGestureEnvironmentSortAndSendDelayedTouches + 4340
    frame #9: 0x000000018ccafc60 UIKit`_UIGestureEnvironmentUpdate + 1236
    frame #10: 0x000000018c74a4d8 UIKit`-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404
    frame #11: 0x000000018c74a010 UIKit`-[UIGestureEnvironment _updateGesturesForEvent:window:] + 276
    frame #12: 0x000000018c749874 UIKit`-[UIWindow sendEvent:] + 3132
    frame #13: 0x000000018c7481d0 UIKit`-[UIApplication sendEvent:] + 340
    frame #14: 0x0000000100730d54 Freetime`Application.sendEvent(event=0x00000001d011aa60, self=0x0000000147f017c0) at Application.swift:17
    frame #15: 0x0000000100730e18 Freetime`@objc Application.sendEvent(_:) at Application.swift:0
    frame #16: 0x000000018cf29d1c UIKit`__dispatchPreprocessedEventFromEventQueue + 2340
    frame #17: 0x000000018cf2c2c8 UIKit`__handleEventQueueInternal + 4744
    frame #18: 0x000000018cf25368 UIKit`__handleHIDEventFetcherDrain + 152
    frame #19: 0x000000018290b404 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
    frame #20: 0x000000018290ac2c CoreFoundation`__CFRunLoopDoSources0 + 276
    frame #21: 0x000000018290879c CoreFoundation`__CFRunLoopRun + 1204
    frame #22: 0x0000000182828da8 CoreFoundation`CFRunLoopRunSpecific + 552
    frame #23: 0x000000018480e020 GraphicsServices`GSEventRunModal + 100
    frame #24: 0x000000018c848758 UIKit`UIApplicationMain + 236
    frame #25: 0x00000001003153f0 Freetime`main at main.swift:11
    frame #26: 0x00000001822b9fc0 libdyld.dylib`start + 4
(lldb) 

Whenever the touch is slow, it's _always_ around 0.35 seconds of delay.

The interesting bit in the fast-response trace is this:

frame #10: 0x000000018c74a4d8 UIKit`-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404
    frame #11: 0x000000018c74a010 UIKit`-[UIGestureEnvironment _updateGesturesForEvent:window:] + 276
    frame #12: 0x000000018c749874 UIKit`-[UIWindow sendEvent:] + 3132
    frame #13: 0x000000018c7481d0 UIKit`-[UIApplication sendEvent:] + 340
    frame #14: 0x0000000100730d54 Freetime`Application.sendEvent(event=0x00000001d011aa60, self=0x0000000147f017c0) at Application.swift:17
    frame #15: 0x0000000100730e18 Freetime`@objc Application.sendEvent(_:) at Application.swift:0
    frame #16: 0x000000018cf29d1c UIKit`__dispatchPreprocessedEventFromEventQueue + 2340
    frame #17: 0x000000018cf2c2c8 UIKit`__handleEventQueueInternal + 4744
    frame #18: 0x000000018cf25368 UIKit`__handleHIDEventFetcherDrain + 152
    frame #19: 0x000000018290b404 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24

__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__

Some reading about the different runloop methods here:

CFRunLoopSources ā€œVersion 0ā€ and ā€œVersion 1ā€ are actually very different beasts, even if they have a common API. Version 0 Sources are simply an in-app messaging mechanism and must be handled manually by the application code. After signaling a Version 0 Source (with CFRunLoopSourceSignal()), the CFRunLoop must be awaken (with CFRunLoopWakeUp()) for the source to be handled.

__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__

Observers are a bit special. The CFRunLoopObserver API lets you observe the behavior of CFRunLoop and be notified of its activity: when it processes events, when it goes to sleep, etc. It’s mostly useful for debugging, and you probably won’t need it in your app, but it’s there if you want to experiment with CFRunLoop’s features. [Update 2014-10-02: In fact, there are certain purposes where it will be useful: for example, CoreAnimation runs from an observer callout. It makes sense: by making sure all the UI code has run, it executes all the animations at once.]

Ah, found it. It's b/c there's already a UITapGestureRecognizer on IssueCommentBaseCell for the double-tap to like. Disabling that gesture fixes everything.

Thanks for sharing your investigation :)

Sent with GitHawk

@rnystrom how'd you measure the time between the UIEvent being called and .touchUpInside being executed? Did the stack traces have anything to do w/ your final solution?

@BrianLitwin subclasses UIApplication and overrode sendEvent(). Set a global Date every time that’s called. Then in button action I print timeIntervalSinceNow.

Sent with GitHawk

Cool. That’s smart

Sent with GitHawk

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jessesquires picture jessesquires  Ā·  3Comments

rnystrom picture rnystrom  Ā·  3Comments

rnystrom picture rnystrom  Ā·  3Comments

BasThomas picture BasThomas  Ā·  3Comments

BasThomas picture BasThomas  Ā·  3Comments