PromiseKit / CoreLocation

Promises for Swift & ObjC
http://promisekit.org
MIT License
30 stars 29 forks source link

Request authorization Always doesn't return after being changed in Settings #18

Open ricsantos opened 6 years ago

ricsantos commented 6 years ago

Latest PromiseKit 6.2.6, which kindly had a fix for #16 in it (🙏) seems to have introduced a regression.

The same test app can be used to reproduce the issue, but with a different sequence of events.

Steps:

Expected result:

Actual result:

Also of note, subsequent launches of the app will fail to complete the chain.

mxcl commented 6 years ago

Oh geez. This stuff is not particularly testable, so we have no tests. Sorry.

mxcl commented 6 years ago

Yeah I can see why this would happen, though I'm surprised it didn't happen before.

mxcl commented 6 years ago

Not a regression, Apple don’t fire any CLLocationManagerDelegate method at all when the user chooses the when In Use option for the upgrade alert.

So… not sure if we can even detect this.

mxcl commented 6 years ago

We can probably listen for the became foreground system notification, but this is a hack.

mxcl commented 6 years ago

I guess our only option is to reject the promise when attempting to upgrade and output a warning to the console telling the user to upgrade manually with a link to this ticket.

ricsantos commented 6 years ago

Oh dear, you are indeed correct. I think this is worthy of a TSI.

ricsantos commented 6 years ago

So I created a TSI with Apple yesterday, and received a response today:

Obviously, there is no “authorization did not change” notification sent to apps.

One thing you can check is the applicationWillResignActive() and applicationDidBecomeActive() app delegate methods (or the corresponding notifications) to know when the user has returned from the prompt. When the system prompt pops up, you app will resign active. You can check this state (and the knowledge that you have just asked for authorization) to determine it is time to check what the auth level is when the applications becomes active again.

I agree this feels rather hacky.

ricsantos commented 6 years ago

I updated the 'CoreLocationTest' to have an implementation of requesting authorization using application state notifications instead of the location manager delegate. It works, as expected, but also requires a piece of persisted state haveRequestedAlways to know if the always alert will be shown or not.

This probably isn't a suitable solution for PromiseKit though, which is a shame.

mxcl commented 6 years ago

Nice research.

My main issue with using the resign active stuff is some other system event could trigger it, eg battery low. So the promise cannot be 100% reliable. Well, at least it seems like we couldn’t be.