16

I am working on Cordova application. Where i am connecting to a real time sensor and reading some data from the sensor. Problem is the data is scrambled when i scroll the view. This is working in android but not in iOS.

Here is my code snippet.

<div id="right_col">
   <button onclick="clearReceivedData()">Clear Received Data</button>
   <br>
   <div id="receivedData"></div>
</div>


function dataReceivedCallback(data) {
  document.getElementById("receivedData").innerHTML += data.value1 + ": ";
  document.getElementById("receivedData").innerHTML += data.value2 + ":";
  document.getElementById("receivedData").innerHTML += data.value3 + "<br>";
}

dataReceivedCallback will be called for each data received from sensor. This callback also blocking until scroll finished. How to update the ui even while scrolling the UI.

n1stre
  • 5,856
  • 4
  • 20
  • 41
naresh
  • 627
  • 1
  • 7
  • 28
  • Can you provide few details like, which version of iOS this is not working? Did you test in lower versions of iOS? Are you using any pagination? – sSD Dec 19 '17 at 13:19
  • I can see this issue in all the iOS devices starting from iOS 9 to iOS 11. No pagination was used. UI will grow with the data. – naresh Dec 19 '17 at 13:35
  • You can check out if this helps. http://patrickmuff.ch/blog/2014/10/01/how-we-fixed-the-webkit-overflow-scrolling-touch-bug-on-ios/ – sSD Dec 19 '17 at 13:38
  • I referred this link already. my problem was dataReceivedCallback not calling when scrolling. – naresh Dec 19 '17 at 13:56
  • Can you put the code where you are binding the 'scroll' event ? – sSD Dec 19 '17 at 13:59
  • I didn't add any scroll events, Its default behaviour of the UIWebView – naresh Dec 29 '17 at 06:26
  • Can you put the code where you are calling 'dataReceivedCallback' ? Is there any way you can show a sample running code of what you are trying? – sSD Dec 29 '17 at 08:13
  • it will be called from iOS native framework. when there is change in sensor data, it will call this method. – naresh Dec 29 '17 at 09:10
  • Your comments are not matching. You said 'dataReceivedCallback not calling when scrolling' and ' when there is change in sensor data, it will call this method' . When is the need to be called exactly? When trying to 'scroll' the page, or when there is any update to data (assuming you are doing a continuous backend fetch), you will call this method from iOS implementation file? – sSD Dec 29 '17 at 09:21
  • dataReceivedCallback will be called continuously when data changed in sensor. This will be handle in native iOS framework and its working properly. While scrolling the screen this method is not being called. I want this function to be called even when the screen is scrolling. – naresh Dec 29 '17 at 11:01
  • This kinda sounds like a focus problem, like when youre scrolling on ios maybe it loses focus from the main window and is handled natively, so it might be possible the data is sent to the wrong window whike scrolling. Is there any way in hell i can get my hands on your app so i can test it myself? – Simon Hyll Jan 03 '18 at 06:45
  • This is actually an issue specific to the UIWebView in Cordova on iOS 8. There is no available fix yet due to a conflicting major bug that's blocking the update for WebViews. Here's a relevant article that includes a description of the issue – refer to the "One caveat for Cordova developers" section about halfway down the page for the problem you're having: https://developer.telerik.com/featured/scroll-event-change-ios-8-big-deal/ – musicinmyhead Jan 03 '18 at 16:20
  • 1
    Is it possible to create a new thread for the native ui code, and add an event listener on the UIWebView? If the callback is not being called while scrolling, would assume the scroll is blocking your native code from executing, which a new thread could solve. I would look into hooking this all in to events because with the native code running concurrently the setup is asynchronous and emitting an event will help to decouple these two parts of the system and let the webview decide when your JS code to update the view gets called... – John Halbert Jan 04 '18 at 19:58
  • Seems @musicinmyhead provided url has the same issue i have. John Halbert, Native code is not blocking. Its sending events continuously to the cordova plugin. Its issue with the UIWebView. – naresh Jan 08 '18 at 09:18

2 Answers2

1

iOS pauses JS execution during scroll to deliver smooth scrolling experience. Apple suggest to use passive event listeners for scroll. There is no solution to your problem even based on the other answer that tries to debounce the execution. You could try to set passive to true:

something.addEventListener("scroll", callback, { passive: true })

Although it could improve your situation, most probably won't fix the issue you are having on iOS.

Try wrapping your code in requestIdleCallback or requestAnimationFrame.

Make sure you are following the advise for not accessing the DOM tree more than once.

Martin Chaov
  • 824
  • 7
  • 17
0

I don't exactly understand your case 100% but here what I think you should do:

1- Access innerHTML as few times as possible, every time you read or write an element property you force a document re-render, down below is a much better approach.

function dataReceivedCallback(data) {
  var newHTML = '';
  newHTML  += data.value1 + ": ";
  newHTML  += data.value2 + ":";
  newHTML  += data.value3 + "<br>";
  document.getElementById("receivedData").innerHTML += newHTML;
}

As you can see we are accessing the innerHTML only once instead of 3

2- You need to let some room for the browser to handle the scroll event, so you need to update the ui using asynchronous function, a timeout function can be utilized to do so likewise:

var timeoutHandller;
function dataReceivedCallback(data) {
  clearTimeout(timeoutHandller);
  timeoutHandller = setTimeout(function() {

    var newHTML = '';
    newHTML  += data.value1 + ": ";
    newHTML  += data.value2 + ":";
    newHTML  += data.value3 + "<br>";
    document.getElementById("receivedData").innerHTML += newHTML;
  }, 150);
}

Now the UI update will only trigger once every 150ms which should leave plenty of room for the scroll event to get handled.

Zahema
  • 1,345
  • 2
  • 19
  • 35