[ios] Mapbox's Location Manager new API.#12013
Conversation
4529f05 to
4891635
Compare
|
|
||
| @optional | ||
|
|
||
| @end |
There was a problem hiding this comment.
I would suggest removing the usage of all CoreLocation types (including CLAuthorizationStatus , etc. — so that you can remove the CoreLocation import above). This has the following reasons:
- Some of them are difficult to initialize.
CLHeadinghas no public initializer so that I was forced to create a subclass where I was overriding thetrueHeadingproperty. This was hacky and not obvious. - You can only reuqest the values you really need. Instead of
CLHeadingcou can ask for thetrueHeading:(double):trueHeading. This makes the API easier to integrate and simulate. - You are getting completely independent of the
CoreLocationframework
There was a problem hiding this comment.
Hi, @simonseyer. Thank you for your feedback, and agree with you. When I was designing the API I consider removing completely the dependency on CoreLocation (provide our version of CLLocation, CLLocationCoordinate2D,CLHeading, etc). Although making that change will require a new semver, and migrating code.
I will follow up with a ticket related to remove CoreLocation dependency.
4891635 to
91bc574
Compare
| @required | ||
|
|
||
| /** | ||
| The delegate to recive updates. |
|
|
||
| - (void)setHeadingOrientation:(CLDeviceOrientation)headingOrientation | ||
| { | ||
| _locationManager.headingOrientation = headingOrientation; |
There was a problem hiding this comment.
Why not self.locationManager... here?
| self.locationManager = [[CLLocationManager alloc] init]; | ||
| // If no custom location manager is provided will use the internal implementation. | ||
| if (!self.locationManager) { | ||
| self.locationManager = [[MGLCLLocationManager alloc] init]; |
There was a problem hiding this comment.
This will call -validateLocationServices again, won't it?
There was a problem hiding this comment.
There was a problem hiding this comment.
Perfect :) Looks like I was commenting on an earlier version.
|
Just picking up from @simonseyer's comment (#12013 (comment)) about removing CoreLocation references (I'm assuming here that you mean only removing CoreLocation in terms of the location manager, not from the wider SDK). This should be our ideal goal, so
In addition, I wonder if it's worth discussing if and how we could improve the user-authorization dance that developers have to go through. |
I meant the wider SDK.
If we replace CLXXXX with our own versions — MGLLocation, MGLHeading, MGLLocationCoordinate — will break the current apps and will require a simple(?) migration.
We may not want to go full without CL but we can replace some classes/structs/enums that makes sense in the line of allowing customization — MGLHeading? MGLAuthorizationStatus? etc —
As I outlined above. I am thinking redefinition.
We can make a ticket to follow along the discussion just as I am waiting to release this to followup with a ticket for going full and replace CL. |
Sounds good. Protocols for the classes (e.g If we drop the CL dependency for this location manager protocol - is it worth considering tweaking the interface? |
|
I performed an allocations and time profiler test iterating over the options in I used an iPhone X iOS 11.4. Allocations.
The internal implementation added 32 bytes to the memory growth. Time Profiler.
It was almost the same time of execution. I performed more tests with 1-2 s deltas. I think is due to the inconsistent location updates I get at our San Francisco office. |
d03fa07 to
e4465d1
Compare
e4465d1 to
5af4080
Compare
1ec5
left a comment
There was a problem hiding this comment.
This PR takes a first step towards making the map view’s built-in location-related features more customizable, which is a laudable goal.
However, I’m uneasy with the idea of eliminating our dependency on Core Location. While doing so could be a boon for a relative few developers with specialized needs, it could potentially complicate most developers’ ability to use the SDK. That would be akin to Apple’s new Natural Language framework shipping with a custom NLString type that you have to use instead of String.
Even with just this more limited refactoring of CLLocationManager usage, I think we should give a lot of thought to the tradeoffs involved and whether the use cases we’d be unblocking would be worth the trouble we’d cause the general user base. Consider the impact these changes will have on someone migrating from MapKit or the Google Maps SDK.
What do these changes mean for MGLMapViewDelegate’s location-related methods? Do we need to document any changes there?
What do these changes mean for telemetry? Would it be problematic if the map view uses one location manager while the telemetry subsystem uses another? On the flip side, would it be problematic to allow the developer to override the location manager used for telemetry?
Remember to update the iOS changelog to note the addition of MGLMapView.locationManager.
|
|
||
| @interface MGLCLLocationManager()<CLLocationManagerDelegate> | ||
|
|
||
| @property (nonatomic) CLLocationManager *locationManager; |
There was a problem hiding this comment.
Why create a default location manager that owns a CLLocationManager? Why not extend CLLocationManager to conform to MGLLocationManager?
There was a problem hiding this comment.
Te reason for MGLCLLocationManager to implement MGLLocationManager is that MGLMapView uses the latter for handling authorization/start/stop events and breaks the dependency on CLLocationManager.
There was a problem hiding this comment.
Suppose we instead declare a category on CLLocationManager that conforms to MGLLocationManager. Wouldn’t that accomplish the same thing as this class, except with less indirection?
There was a problem hiding this comment.
You're right. I changed the implementation accordingly.
| @interface MGLMapView () <UIGestureRecognizerDelegate, | ||
| GLKViewDelegate, | ||
| CLLocationManagerDelegate, | ||
| MGLLocationManagerDelegate, |
There was a problem hiding this comment.
Note that the navigation SDK currently depends on MGLMapView conforming to CLLocationManagerDelegate. I’m unsure whether the navigation SDK still takes advantage of that assumption following mapbox/mapbox-navigation-ios#402.
/cc @bsudekum @frederoni
There was a problem hiding this comment.
The navigation SDK’s redeclaration of this conformance was vestigial: mapbox/mapbox-navigation-ios#1549.
| events. | ||
|
|
||
| If no custom manager is provided or setting this property to `nil` will default | ||
| to the internal `CLLocationManager` based implementation. |
There was a problem hiding this comment.
If the default use of CLLocationManager is an internal implementation detail, then we shouldn’t mention it.
There was a problem hiding this comment.
How can we communicate this behavior? We should let devs know that this is a specialized API and if nothing is provided then the default option is used.
There was a problem hiding this comment.
We can certainly say that a typical implementation comes with MGLMapView by default, but if the goal is to reduce dependency on CLLocationManager, then we need to couple any mention of CLLocationManager in the documentation with a note that the default location manager may change in the future.
| - (void)setLocationManager:(id<MGLLocationManager>)locationManager | ||
| { | ||
| _locationManager = locationManager; | ||
| _locationManager.delegate = self; |
There was a problem hiding this comment.
The documentation comment for this property states that setting the property to nil causes the map view to use the CLLocationManager implementation. Does that happen immediately, or upon the next location update?
There was a problem hiding this comment.
When the location manager is set to nil is going to use the default option the next time the showsUserLocation is set to yes.
There was a problem hiding this comment.
So MGLMapView would continue to serve as the old location manager’s delegate until then, without stopping that location manager? That could result in MGLMapView and MGLMapViewDelegate responding to doubled-up or contradictory location updates.
|
|
||
| Set the custom location manager before calling `showUserLocation`. | ||
| */ | ||
| @property (nonatomic, nullable) id<MGLLocationManager> locationManager; |
There was a problem hiding this comment.
If the developer sets this property to nil or leaves it as nil, should the getter return nil or should it return the default implementation? If the latter, then the property should be null_resettable instead of nullable.
Most of the time we’ve received requests to expose the location manager, it wasn’t because the developer wanted to replace the location manager with their own implementation. Rather, it was because they wanted to tweak the built-in location manager’s settings. For that to be possible, this property would always need to return a non-nil value.
I understand your worries. Reducing our direct dependency on Core Location may bring new problems. In one of my previous comments I stated that we may not replace entirely our dependency but that is up to a conscious analysis. I also don't believe that radical changes are good for devs but I do believe on evolutionary changes. Enabling greater customization will require some evolutionary changes. It's familiar for devs to remove prefixes from Classes and what would be the worst scenario besides renaming CLLocation to MGLLocation? — please help me understand —
What kind of problems do you think it may arise?
This does not affect
I don't have a clear answer for this. The telemetry parts that are used inside |
That change alone is benign, given that we don’t currently use CLLocation anywhere in the public API. I was responding to the suggestion that we remove the dependency on Core Location, which would require replacing important types like CLLocationCoordinate2D and CLLocationDirection with types specific to this SDK. Unlike on Android, our various iOS libraries don’t share a common dependency that vends core types the way the Mapbox Java SDK does: mapbox/mapbox-events-ios#1.
My understanding is that the set of developers who’d need to use this SDK with a different location manager is a relatively small subset. They may be an important subset, but perhaps that’s a discussion to have elsewhere. Most developers would at most need to configure a few CLLocation parameters rather than creating their own. I think making the |
5af4080 to
cc4a2b2
Compare
6221531 to
38306ba
Compare
…ng updates after set to nil.
09aaa6b to
f01e324
Compare
* [ios] Cherry-pick 12013 * [ios] Updated Changelog.md * [ios] Fix MBXCustomLocationViewController iOS 8 compatibility.




This PR fixes #11983 and adds a new API to implement a custom location manager.
This API follows Apple's rule that is possible to have only one location manager at a given time, but opens the option to have different technologies that provides location updates such as WIFI or iBeacons.
MGLLocationManagerandMGLLocationManagerDelegate.MGLMapViewto use the new API.