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

iOS 16 CDVLocation.m throwing UI unresponsiveness warning in XCode - causing app to crash. #257

Open
rolinger opened this issue Feb 27, 2023 · 12 comments · May be fixed by #290
Open

iOS 16 CDVLocation.m throwing UI unresponsiveness warning in XCode - causing app to crash. #257

rolinger opened this issue Feb 27, 2023 · 12 comments · May be fixed by #290

Comments

@rolinger
Copy link

Bug Report

A new feature in Xcode 14 is displaying purple warnings about UI Unresponsiveness coming from CDVLocation.m#L89 - this issue seems specific to iOS 16x too. Its a part of the isLocationServicesEnabled function.

This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationManagerDidChangeAuthorization:callback and checkingauthorizationStatus first.

The warning gets thrown about 50 times too (not certain why though). I and others (on different forums) are experience app freeze/crashes with some getting apps rejected from app store.

Problem

iOS 16 apparently has changed behavior regarding location permission checks - the specific code commented with iOS 4.x - so it looks like a fix for iOS 4 and has worked all the way through iOS 15 is now causing issues.

What is expected to happen?

Work cleanly without throwing warnings.

What does actually happen?

Throws the above warning.

Environment, Platform, Device

Mac 13.2.1 Ventura
Xcode 14.2

Version information

Cordova 11
cordova-ios: 6.2.0
iOS: 16.x

Checklist

  • [x ] I searched for existing GitHub issues
  • [x ] I updated all Cordova tooling to most recent version
  • [x ] I included all the necessary information above
@rolinger
Copy link
Author

Also on CDVLocation.m, XCode 14 is now throwing Alerts on line #216
Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

#216
if (!__locationStarted || (__highAccuracyEngaled != enableHIghAccuracy)) {

I think should be:
if (!__locationStarted || (__highAccuracyEngaled != self enableHIghAccuracy)) {

@snblackout
Copy link

Has anyone found a fork out there with this fix or have any idea how to solve this? I have an app update being blocked from release at Apple because of this. I hope I don't have to do a full re-write...

@breautek
Copy link
Contributor

breautek commented Jan 9, 2024

Has anyone found a fork out there with this fix or have any idea how to solve this? I have an app update being blocked from release at Apple because of this. I hope I don't have to do a full re-write...

Not aware of any forks but a rewrite shouldn't be necessary. The warning is caused by some APIs that checks states on the location manager, which may block for a long time so it isn't desirable to call on the main thread. If it does block for a significant of time, it will make hte app unresponsive since it will block UI updates. So the solution is to not call on those checks on the main thread.

However it's not as trivial as simply wrapping the code in a background block. The CLLocationManager instance is only safe to use on the thread/dispatch queue it was created in.

So the solution is probably to create a dispatch queue for geolocation usage and have the CLLocationManager initialized in that queue, as well as any cordova calls to switch to that queue when performing location manager calls. And of course to return back to the main queue when calling back to the webview.

@snblackout

This comment was marked as off-topic.

@breautek

This comment was marked as off-topic.

@snblackout

This comment was marked as off-topic.

@snblackout

This comment was marked as off-topic.

kumo01GitHub added a commit to kumo01GitHub/cordova-plugin-geolocation that referenced this issue Jan 4, 2025
@rolinger
Copy link
Author

rolinger commented Jan 6, 2025

When I opened this nearly two years ago geolocation was on like version 4.0 or 4.1, and now we are up to 5.0. I am still getting these errors thrown in all my latest upgrade to cordova-plugin-geolocation v5.0 (and to Cordova12, cordova-ios v7.1.1, on Xcode 16.2 ).

I see that @kumo01GitHub has committed a fix for this...however, upon further inspection it appears the fix is simply to remove the warning as opposed to actually fixing the issue. Is this the case? If it is a fix, when can it be fully committed....if its just removing the warning without a true fix what is the risk here?

Last, trying to analyze the original issue, and I am wondering what is considered "the main thread?" I keep thinking this is an error specifically from within geolocation, but is this originating from where I am calling geolocation in my app? If so, what is considered the main thread from within the app? Wondering if I can move some code around in my app that would eliminate this.

@breautek
Copy link
Contributor

breautek commented Jan 6, 2025

The main thread refers to the main application event loop. This is often (and is the case for iOS apps) tied to the UI, so sometimes the main thread is also called the UI thread. Blocking the main thread will cause the UI to become unresponsive, and make the app feel laggy, or choppy. The geolocation API being used is being called on the main thread, and that API uses networking/gps hardware that can take a long time to complete, and has a risk of blocking the UI from updating, hence the warning.

Additionally, iOS has a "watchdog" that monitors app's main threads and if they are blocked for 3-5 seconds ios can kill the app, causing an app crash, which is another reason why blocking the main thread is dangerous.

I just had a glance at #283 and I think it's mislabeled. #283 wouldn't address this issue. It's changing code to explicitly reference self to make self retainment more obvious (because it's being used by an inner block of code. That has nothing to do with the geolocation warning on using the main thread.

He has a different commit that looks like it would solve this issue by moving the offending code off the main thread, but I'm not sure if there is a PR created.

@rolinger
Copy link
Author

rolinger commented Jan 6, 2025

Ok, so to clarify, there is nothing I can specifically do in my App that would eliminate this error? It really is an issue inside of cordova-plugin-geolocation?

This entire upgrade effort and see the above error still happen triggered me into doing some extensive testing. My app requires GPS. When my app initializes I call a function every 1 second for the first 15 seconds, then every 3 seconds up to the first 45 seconds and then every 10 seconds after that. GPS usually takes about 30 to 45 seconds to truly get the most accurate user location. so for the first 45 seconds after app starts I am aggressively trying to get the users exact location.....then after the first 45 seconds I back off the aggressive ness and update the users position (in the app) about every 10 seconds. I am using this function to do this:

function setupWatch() {
  // global var here so it can be cleared on logout (or whenever).
  // call every second for first 15 seconds; watchCount < 15
  // then call for every 3 seconds for til 45 seconds
  // after 45 seconds, call once per 10 seconds

 // watchCount intializes to 0, and then is set to 1 when GPS enabled AND user has granted permissions
  if (watchCount > 0) {
    getPosition();
  }
  if (watchCount == 15) {
    watchDelay = 3000 ;
  } else if (watchCount == 25) {
    watchDelay = 10000 ;  // after 45 seconds, run every 10 seconds
  }
  watchCount++ ;
  watchValue = setTimeout(setupWatch,watchDelay)
}

getPosition() calls the geolocation plugin with:
watchID = navigator.geolocation.getCurrentPosition(onSuccess, onError, options);

Everytime getCurrentPosition() is called Xcode tracks the error. Is there a better method to track the user location changes other than having to call getCurrentPosition() every 10 seconds? I would really like to get rid of this error I am getting in Xcode/iOS and am wondering if a better method would help me eliminate the error.

@rolinger
Copy link
Author

rolinger commented Jan 6, 2025

uhhh....just looked at the plugin again, the watchPosition() would be what I need for a better method. I honestly have no idea how I over looked this. My only explanation was in years past I couldn't get something to work and abandoned watchPosition() for my own watch method. I can't recall. Need to rethink this one. Hopefully it eliminates the above error except for the first/only time getCurrentPosition() gets called instead of every 10 seconds like I am doing now.

Egg on my face. :-(

@kumo01GitHub
Copy link

kumo01GitHub commented Jan 15, 2025

I'm sorry that #283 is only address this part:

Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

This commit might help this issue and it looks no problem with simple operation check but as comment on code, I couldn't resolve below. So, I didn't make PR yet:

The CLLocationManager instance is only safe to use on the thread/dispatch queue it was created in.

@kumo01GitHub kumo01GitHub linked a pull request Jan 18, 2025 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants