-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[ios] Mapbox's Location Manager new API. #12013
Conversation
4529f05
to
4891635
Compare
|
||
@optional | ||
|
||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
CLHeading
has no public initializer so that I was forced to create a subclass where I was overriding thetrueHeading
property. This was hacky and not obvious. - You can only reuqest the values you really need. Instead of
CLHeading
cou can ask for thetrueHeading:(double):trueHeading
. This makes the API easier to integrate and simulate. - You are getting completely independent of the
CoreLocation
framework
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: recive
-> receive
|
||
- (void)setHeadingOrientation:(CLDeviceOrientation)headingOrientation | ||
{ | ||
_locationManager.headingOrientation = headingOrientation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will call -validateLocationServices
again, won't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I changed the implementation accordingly.
@@ -184,7 +185,7 @@ typedef NS_ENUM(NSUInteger, MGLUserTrackingState) { | |||
|
|||
@interface MGLMapView () <UIGestureRecognizerDelegate, | |||
GLKViewDelegate, | |||
CLLocationManagerDelegate, | |||
MGLLocationManagerDelegate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The navigation SDK’s redeclaration of this conformance was vestigial: mapbox/mapbox-navigation-ios#1549.
platform/ios/src/MGLMapView.h
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the default use of CLLocationManager is an internal implementation detail, then we shouldn’t mention it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
platform/ios/src/MGLMapView.mm
Outdated
- (void)setLocationManager:(id<MGLLocationManager>)locationManager | ||
{ | ||
_locationManager = locationManager; | ||
_locationManager.delegate = self; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
platform/ios/src/MGLMapView.h
Outdated
|
||
Set the custom location manager before calling `showUserLocation`. | ||
*/ | ||
@property (nonatomic, nullable) id<MGLLocationManager> locationManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
MGLLocationManager
andMGLLocationManagerDelegate
.MGLMapView
to use the new API.