Search code examples
javascriptiostouchios9mobile-safari

Mobile Safari (iOS 9) Touch.clientX/Y not reified at time of dispatch?


A simple method for calculating a delta between touchmove events might look like:

var lastEvent;
window.addEventListener('touchmove', function(event) {
  if (lastEvent) {
    console.log(event.touches[0].clientY - lastEvent.touches[0].clientY);
  }
  lastEvent = event;
});

On iOS 9, though, this delta is always 0 for contiguous touchmove events (sandwiched between the same touchstart and touchend events).

On iOS 10 the delta is calculated as you might expect.

I don't understand why!


Solution

  • Modifying the example to add additional inspection:

    var lastEvent;
    window.addEventListener('touchmove', function(event) {
      if (lastEvent) {
        console.log('same event?', event === lastEvent)
        console.log('same touch?', event.touches[0] === lastEvent.touches[0])
        console.log('delta', event.touches[0].clientY - lastEvent.touches[0].clientY);
      }
      lastEvent = event;
    });
    

    Yields:

    same event? false
    same touch? true
    delta 0
    

    It seems that iOS 9 is creating new event objects every dispatch, but recycling Touch objects in the touches array.

    The code works as expected in iOS 10 because it does not seem to do the same Touch object pooling.

    I'm going to mark this as the answer, but if anyone happens to know anything relevant re: Touch object recycling or related optimizations (i assume this is an optimization...) in WebKit, please share!