Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tap missed / taps ignored #15606

Closed
jslz opened this issue Aug 22, 2017 · 10 comments
Closed

Tap missed / taps ignored #15606

jslz opened this issue Aug 22, 2017 · 10 comments
Labels
Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@jslz
Copy link

jslz commented Aug 22, 2017

Is this a bug report?

Yes, this is a bug report.

Have you read the Contributing Guidelines?

Yes, I have read it.

Environment

  1. react-native -v: react-native-cli: 2.0.1 react-native: 0.46.4
  2. node -v: v6.11.1
  3. npm -v: 5.3.0
  4. yarn --version: 0.27.5

Then, specify:

  • Target Platform:

iOS and Android

  • Development Operating System:

Mac OS X 10.12.6

  • Build tools:

For iOS release we are building via Xcode / Archive / upload to TestFlight. See down below for package.json.

Steps to Reproduce

With our app's iOS release builds (unclear/untested if it also happens with Android) we are seeing taps on the screen get utterly ignored some times. The 2 main scenarios we reproduce are

  1. there's a harder to repro case where the user scrolls the list some, and then stops the scrolling, and then taps on another component on-screen, and the first tap is ignored/lost/missed/not seen.

  2. more 100% reproducible, while our ListView is scrolling, other things on the screen do not respond to taps. (We have tried using FlatList and for various reasons it is not an acceptable component for us to use, so we're using ListView.)

Expected Behavior

taps should always work and never be missed/lost/ignored.

Actual Behavior

It appears that RN is missing input events. Note that we are not talking about a delay. We are talking about events never being "seen" by the RN system.

  "dependencies": {
    "color": "^1.0.3",
    "moment": "^2.18.1",
    "query-string": "^4.3.4",
    "react": "16.0.0-alpha.12",
    "react-native": "0.46.4",
    "react-native-branch": "^2.0.0-beta.7",
    "react-native-code-push": "^2.1.0-beta",
    "react-native-contacts": "^0.8.1",
    "react-native-device-info": "^0.10.2",
    "react-native-dismiss-keyboard": "^1.0.0",
    "react-native-fabric": "^0.4.1",
    "react-native-fbsdk": "^0.6.0",
    "react-native-fcm": "tjlian616/react-native-fcm#503dd7a",
    "react-native-fetch-blob": "^0.10.8",
    "react-native-fs": "^2.5.1",
    "react-native-image-picker": "^0.26.3",
    "react-native-mail": "^3.0.4",
    "react-native-material-design-styles": "^0.2.6",
    "react-native-orientation": "^2.0.0",
    "react-native-progress": "^3.2.1",
    "react-native-sentry": "^0.14.0",
    "react-native-simple-toast": "0.0.6",
    "react-native-ux-cam": "^3.4.0",
    "react-native-view-shot": "^1.10.1",
    "react-native-youtube": "1.0.0-beta.2",
    "react-navigation": "^1.0.0-beta.9",
    "react-redux": "^5.0.5",
    "redux": "^3.6.0",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.2.0",
    "seamless-immutable": "^7.1.2"
  },
  "devDependencies": {
    "@google-cloud/storage": "^1.2.1",
    "babel-eslint": "^7.2.3",
    "babel-jest": "20.0.3",
    "babel-preset-react-native": "^1.9.2",
    "code-push-cli": "^2.0.0-beta",
    "eslint": "^3.19.0",
    "eslint-config-rallycoding": "^3.2.0",
    "eslint-plugin-react": "^7.1.0",
    "eslint-plugin-react-native": "^2.3.2",
    "flow-bin": "^0.47.0",
    "jest": "20.0.3",
    "mailgun-js": "^0.13.1",
    "react-test-renderer": "16.0.0-alpha.6",
    "redux-mock-store": "^1.2.3"
  },
@jslz
Copy link
Author

jslz commented Aug 22, 2017

If anybody knows where in the RN system I could put debug logging to see if the underlying native layer is getting the events, that would be potentially helpful to know, so we can try to do some/any debugging about it.

Update: Following the ideas from this https://stackoverflow.com/a/35619964/8168867 stack overflow post, I added iOS native level logging of events to our app. In the non-scrolling missing-taps case, I do see the iOS native level getting the events. So something about the RN level is utterly missing / ignoring / dropping those events.

@jslz
Copy link
Author

jslz commented Aug 22, 2017

Update: So far, it appears that the ListView is eating up CPU time (or something) for a while even after scrolling has visibly stopped. We've experimented with various combinations of having and not-having ListViews and trying to repro, and it doesn't repro when the ListView is not in use. Whereas if we do have the ListView and scroll-and-stop and then tap, the fist tap or so is lost.

The window of time that the first tap will be missed after scrolling appears to depend on the phone e.g. our iPhone6 seems to be faster / less likely to repro the issue / reduces the window of time after scrolling in which the bug manifests.

Question: Does anybody know if there's anything we can do about this? Is there a way to get ListView to do less work after scrolling has visibly stopped? (ideally, not including switching to FlatList since we have done extensive attempts to use FL and they have all been much worse than using LV. In particular, the window of time after scrolling during which the taps are ignored is way worse in our experience with FL.)

@jslz
Copy link
Author

jslz commented Aug 22, 2017

Question: why/how/are the iOS native level events not/going into a native level Q that the JS UI thread then reads from when it gets a chance? That would convert our problem of completely missing some events over into the other classic UX problem of a system that responds to events with lag. That probably would be better overall, though not ideal of course.

Update: I hacked in some more NSLog()s and it appears that in the missed-tap-after-scroll case the iOS native code is calling "[_bridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]];" successfully. I don't know if that's the right place to be concerned with. I haven't dug deeper to see if "enqueueJSCall" is dropping the event before it gets to the JS side.

Update 2, 3, 4, 5: I had some very red herring wild goose chase logging traces for a while. Simplifying our app, the two cases now look the same. Which leads me to think the event is ok in the iOS native layer, but is getting lost somehow on the JS side??

JS did not see this touch:

2017-08-22 15:13:51.091718-0700 X[4867:1476710] touchesEnded
2017-08-22 15:13:51.091833-0700 X[4867:1476710] _update: found? 1
2017-08-22 15:13:51.092046-0700 X[4867:1476710] _update: sendEvent: <RCTTouchEvent: 0x170845040; name = touchEnd; coalescing key = 35>
2017-08-22 15:13:51.092079-0700 X[4867:1476710] sendEvent
2017-08-22 15:13:51.093043-0700 X[4867:1476710] sendEvent: <UITouchesEvent: 0x1740f7d00> timestamp: 367238 touches: {(
    <UITouch: 0x1010f3df0> phase: Ended tap count: 1 force: 0.000 window: <UIWindow: 0x10100ac50; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x17405e210>; layer = <UIWindowLayer: 0x174032d60>> view: <RCTImageView: 0x100f97680; baseClass = UIImageView; frame = (0 0; 32 32); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x170431c20>> location in window: {52.333328247070312, 36} previous location in window: {52.333328247070312, 36} location in view: {27.333328247070312, 21} previous location in view: {27.333328247070312, 21}
)}
2017-08-22 15:13:51.099089-0700 X[4867:1476841] dispatchEvent
2017-08-22 15:13:51.102501-0700 X[4867:1476841] enqueueJSCall: self->_reactInstance->callJSFunction RCTEventEmitter receiveTouches (
	0   X                          0x00000001001a3020 __53-[RCTCxxBridge enqueueJSCall:method:args:completion:]_block_invoke + 124
	1   X                          0x00000001001a2adc -[RCTCxxBridge _runAfterLoad:] + 252
	2   X                          0x00000001001a2ed8 -[RCTCxxBridge enqueueJSCall:method:args:completion:] + 236
	3   X                          0x00000001001ebba0 -[RCTBridge enqueueJSCall:args:] + 200
	4   X                          0x00000001001f9024 -[RCTEventDispatcher dispatchEvent:] + 168
	5   X                          0x00000001001f91d4 -[RCTEventDispatcher flushEventsQueue] + 380
	6   X                          0x00000001001c59a0 _ZN8facebook5react17tryAndReturnErrorERKNSt3__18functionIFvvEEE + 24
	7   X                          0x000000010019e914 -[RCTCxxBridge _tryAndHandleError:] + 88
	8   Foundation                          0x000000019133a4cc <redacted> + 340
	9   CoreFoundation                      0x00000001907f542c <redacted> + 24
	10  CoreFoundation                      0x00000001907f4d9c <redacted> + 540
	11  CoreFoundation                      0x00000001907f29a8 <redacted> + 744
	12  CoreFoundation                      0x0000000190722da4 CFRunLoopRunSpecific + 424
	13  X                          0x000000010019e854 -[RCTCxxBridge runJSRunLoop] + 264
	14  Foundation                          0x000000019133a2d8 <redacted> + 996
	15  libsystem_pthread.dylib             0x000000018f90968c <redacted> + 240
	16  libsystem_pthread.dylib             0x000000018f90959c <redacted> + 0
	17  libsystem_pthread.dylib             0x000000018f906cb4 thread_start + 4
)
NativeToJsBridge::callFunction RCTEventEmitter receiveTouches

JS did see this touch:

2017-08-22 15:13:52.906984-0700 X[4867:1476710] touchesEnded
2017-08-22 15:13:52.907131-0700 X[4867:1476710] _update: found? 1
2017-08-22 15:13:52.907449-0700 X[4867:1476710] _update: sendEvent: <RCTTouchEvent: 0x170848a00; name = touchEnd; coalescing key = 39>
2017-08-22 15:13:52.907498-0700 X[4867:1476710] sendEvent
2017-08-22 15:13:52.908962-0700 X[4867:1476710] sendEvent: <UITouchesEvent: 0x1740f7d00> timestamp: 367240 touches: {(
    <UITouch: 0x100fd88a0> phase: Ended tap count: 1 force: 0.000 window: <UIWindow: 0x10100ac50; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x17405e210>; layer = <UIWindowLayer: 0x174032d60>> view: <RCTImageView: 0x100f97680; baseClass = UIImageView; frame = (0 0; 32 32); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x170431c20>> location in window: {43.666656494140625, 26.666656494140625} previous location in window: {43.666656494140625, 26.666656494140625} location in view: {18.666656494140625, 11.666656494140625} previous location in view: {18.666656494140625, 11.666656494140625}
)}
2017-08-22 15:13:52.911091-0700 X[4867:1476841] dispatchEvent
2017-08-22 15:13:52.916517-0700 X[4867:1476841] enqueueJSCall: self->_reactInstance->callJSFunction RCTEventEmitter receiveTouches (
	0   X                          0x00000001001a3020 __53-[RCTCxxBridge enqueueJSCall:method:args:completion:]_block_invoke + 124
	1   X                          0x00000001001a2adc -[RCTCxxBridge _runAfterLoad:] + 252
	2   X                          0x00000001001a2ed8 -[RCTCxxBridge enqueueJSCall:method:args:completion:] + 236
	3   X                          0x00000001001ebba0 -[RCTBridge enqueueJSCall:args:] + 200
	4   X                          0x00000001001f9024 -[RCTEventDispatcher dispatchEvent:] + 168
	5   X                          0x00000001001f91d4 -[RCTEventDispatcher flushEventsQueue] + 380
	6   X                          0x00000001001c59a0 _ZN8facebook5react17tryAndReturnErrorERKNSt3__18functionIFvvEEE + 24
	7   X                          0x000000010019e914 -[RCTCxxBridge _tryAndHandleError:] + 88
	8   Foundation                          0x000000019133a4cc <redacted> + 340
	9   CoreFoundation                      0x00000001907f542c <redacted> + 24
	10  CoreFoundation                      0x00000001907f4d9c <redacted> + 540
	11  CoreFoundation                      0x00000001907f29a8 <redacted> + 744
	12  CoreFoundation                      0x0000000190722da4 CFRunLoopRunSpecific + 424
	13  X                          0x000000010019e854 -[RCTCxxBridge runJSRunLoop] + 264
	14  Foundation                          0x000000019133a2d8 <redacted> + 996
	15  libsystem_pthread.dylib             0x000000018f90968c <redacted> + 240
	16  libsystem_pthread.dylib             0x000000018f90959c <redacted> + 0
	17  libsystem_pthread.dylib             0x000000018f906cb4 thread_start + 4
)
NativeToJsBridge::callFunction RCTEventEmitter receiveTouches

@jslz
Copy link
Author

jslz commented Aug 22, 2017

Update/Tweak/Nuance/Wrinkle: We've actually repro'd on some iOS devices that it isn't a matter of timing, that no matter how long one waits after scrolling the ListView, the first tap is missed in JS.

@ssssssssssss
Copy link

Do you have any progress here ?

@stale
Copy link

stale bot commented Oct 31, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Oct 31, 2017
@Cool04ek
Copy link

Cool04ek commented Nov 1, 2017

Facing same issue as well with react-native 0.44.2

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Nov 1, 2017
@Cool04ek
Copy link

Cool04ek commented Nov 1, 2017

The root of the issue can possibly be read here - negativetwelve/react-native-ux-cam#36

@ognen
Copy link
Contributor

ognen commented Nov 1, 2017

@Cool04ek I can also confirm that by changing the delegate method in RCTTouchHandler.m to always return NO, the problem disappears:

- (BOOL)gestureRecognizer:(__unused UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
	return NO;
}

By examining the git history of this class, I can see that this method was added by @shergin with commit c68a708. Prior to this, the class always returned NO (though w/o a delegate impl). @shergin could you look into this and propose a proper way to fix this issue?

I can provide a test project which demonstrates this behavior.

@stale
Copy link

stale bot commented Dec 31, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 31, 2017
@stale stale bot closed this as completed Jan 7, 2018
@facebook facebook locked and limited conversation to collaborators May 15, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests

4 participants