Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[ios] Mapbox's Location Manager new API. #12013

Merged
merged 23 commits into from Jul 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5959462
[ios] Add MGLLocationManager and MGLLocationManagerDelegate to Mapbox…
fabian-guerra May 25, 2018
16ac785
[ios] MGLMapView update to new location manager API.
fabian-guerra May 30, 2018
6d87719
[ios] Remove team.
fabian-guerra Jun 21, 2018
958a744
[ios] Add API methods to handle heading events.
fabian-guerra Jun 22, 2018
720bb19
[ios] Improve custom location manager documentation.
fabian-guerra Jun 25, 2018
4cfbc74
[ios] Remove CLLocationManager usage.
fabian-guerra Jun 25, 2018
49078d9
[ios] Clarify location manager usage.
fabian-guerra Jun 25, 2018
7d826ec
[ios] Add a custom location manager example.
fabian-guerra Jun 26, 2018
428a99a
[ios] Fix location manager doc typo.
fabian-guerra Jun 26, 2018
5ff6d16
[ios] Fix internal location manager invocation.
fabian-guerra Jun 26, 2018
acf3eaf
[ios] Fix resetting the location manager blocks updates.
fabian-guerra Jul 3, 2018
ba2a196
[ios] Change locationManager to null resettable.
fabian-guerra Jul 3, 2018
65a788d
[ios] Clarify map view's locationManager property usage.
fabian-guerra Jul 10, 2018
3bec307
[ios] Fix an issue where a custom location manager may continue getti…
fabian-guerra Jul 10, 2018
efad42d
[ios] Change the location manager internal implementation to a category.
fabian-guerra Jul 11, 2018
fbd8066
[ios] Clarify location manager's API usage.
fabian-guerra Jul 13, 2018
f1445cb
[ios] Rever the default location manager to the wrap based implementa…
fabian-guerra Jul 17, 2018
6ffc828
[ios] Clarify location manager API use.
fabian-guerra Jul 19, 2018
2d60067
[ios] Add the location API to jazzy.
fabian-guerra Jul 19, 2018
a6cd73c
[ios] Update changelog.
fabian-guerra Jul 19, 2018
741dd3c
[ios] Fix documentation format.
fabian-guerra Jul 20, 2018
f01e324
[ios] Add location manager's error handler.
fabian-guerra Jul 20, 2018
08b4727
[ios] Update location manager API documentation order.
fabian-guerra Jul 20, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
181 changes: 181 additions & 0 deletions platform/darwin/src/MGLLocationManager.h
@@ -0,0 +1,181 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol MGLLocationManagerDelegate;

/**
The `MGLLocationManager` protocol defines a set of methods that a class must
implement in order to serve as the location manager of an `MGLMapView`. A location
manager is responsible for notifying the map view about location-related events,
such as a change in the user’s location. This protocol is similar to the
Core Location framework’s `CLLocationManager` class, but your implementation
does not need to be based on `CLLocationManager`.

*/
@protocol MGLLocationManager <NSObject>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding this protocol and MGLLocationManagerDelegate to the jazzy table of contents.


@optional

#pragma mark Configuring Location Update Precision

/**
Specifies the minimum distance (measured in meters) a device must move horizontally
before a location update is generated.

The default value of this property is `kCLDistanceFilterNone` when `MGLMapView` uses its
default location manager.

@see `CLLocationManager.distanceFilter`
*/
@property(nonatomic, assign) CLLocationDistance distanceFilter;

/**
Specifies the accuracy of the location data.

The default value is `kCLLocationAccuracyBest` when `MGLMapView` uses its
default location manager.

@note Determining a location with greater accuracy requires more time and more power.

@see `CLLocationManager.desiredAccuracy`
*/
@property (nonatomic, assign) CLLocationAccuracy desiredAccuracy;

/**
Specifies the type of user activity associated with the location updates.

The location manager uses this property as a cue to determine when location updates
may be automatically paused.

The default value is `CLActivityTypeOther` when `MGLMapView` uses its
default location manager.

@see `CLLocationManager.activityType`
*/
@property (nonatomic, assign) CLActivityType activityType;

@required

/**
The delegate to receive location updates.

Do not set the location manager’s delegate yourself. `MGLMapView` sets this property
after the location manager becomes `MGLMapView`’s location manager.
*/
@property (nonatomic, weak) id<MGLLocationManagerDelegate> delegate;

#pragma mark Requesting Authorization for Location Services

/**
Returns the current localization authorization status.

@see `+[CLLocationManger authorizationStatus]`

This comment was marked as resolved.

*/
@property (nonatomic, readonly) CLAuthorizationStatus authorizationStatus;

/**
Requests permission to use the location services whenever the app is running.
*/
- (void)requestAlwaysAuthorization;

/**
Requests permission to use the location services while the app is in
the foreground.
*/
- (void)requestWhenInUseAuthorization;

#pragma mark Initiating Location Updates

/**
Starts the generation of location updates that reports the user's current location.
*/
- (void)startUpdatingLocation;

/**
Stops the generation of location updates.
*/
- (void)stopUpdatingLocation;

#pragma mark Initiating Heading Updates

/**
Specifies a physical device orientation.
*/
@property (nonatomic) CLDeviceOrientation headingOrientation;

/**
Starts the generation of heading updates that reports the user's current hading.
*/
- (void)startUpdatingHeading;

/**
Stops the generation of heading updates.
*/
- (void)stopUpdatingHeading;

/**
Dissmisses immediately the heading calibration view from screen.
*/
- (void)dismissHeadingCalibrationDisplay;

@end

/**
The `MGLLocationManagerDelegate` protocol defines a set of methods that respond
to location updates from an `MGLLocationManager` object that is serving as the
location manager of an `MGLMapView`.
*/
@protocol MGLLocationManagerDelegate <NSObject>

#pragma mark Responding to Location Updates

/**
Notifies the delegate with the new location data.

@param manager The location manager reporting the update.
@param locations An array of `CLLocation` objects in chronological order,
with the last object representing the most recent location. This array
contains multiple `CLLocation` objects when `MGLMapView` uses its
default location manager.
*/
- (void)locationManager:(id<MGLLocationManager>)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations;

#pragma mark Responding to Heading Updates

/**
Notifies the delegate with the new heading data.

@param manager The location manager reporting the update.
@param newHeading The new heading update.
*/
- (void)locationManager:(id<MGLLocationManager>)manager
didUpdateHeading:(CLHeading *)newHeading;

/**
Asks the delegate if the calibration alert should be displayed.

@param manager The location manager reporting the calibration.
*/
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(id<MGLLocationManager>)manager;

#pragma mark Responding to Location Updates Errors

/**
Notifies the delegate that the location manager was unable to retrieve
location updates.

@param manager The location manager reporting the error.
@param error An error object containing the error code that indicates
why the location manager failed.
*/
- (void)locationManager:(id<MGLLocationManager>)manager
didFailWithError:(nonnull NSError *)error;

@optional

@end

NS_ASSUME_NONNULL_END
116 changes: 116 additions & 0 deletions platform/darwin/src/MGLLocationManager.m
@@ -0,0 +1,116 @@
#import "MGLLocationManager_Private.h"

@interface MGLCLLocationManager()<CLLocationManagerDelegate>

@property (nonatomic) CLLocationManager *locationManager;
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.


@end

@implementation MGLCLLocationManager

- (instancetype)init
{
if (self = [super init]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need a dealloc with _locationManager.delegate = nil;

CLLocationManager's delegate property is declared as assign, rather than weak.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dealloc is implemented here:

- (void)dealloc
{
[self.locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingHeading];
self.delegate = nil;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! nvm you are saying that the dealloc is missing a _locationManager.delegate = nil;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
return self;
}

@synthesize delegate;

- (void)setHeadingOrientation:(CLDeviceOrientation)headingOrientation
{
self.locationManager.headingOrientation = headingOrientation;
}

- (CLDeviceOrientation)headingOrientation
{
return self.locationManager.headingOrientation;
}

- (void)setDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy {
self.locationManager.desiredAccuracy = desiredAccuracy;
}

- (CLLocationAccuracy)desiredAccuracy {
return self.locationManager.desiredAccuracy;
}

- (CLAuthorizationStatus)authorizationStatus {
return [CLLocationManager authorizationStatus];
}

- (void)setActivityType:(CLActivityType)activityType {
self.locationManager.activityType = activityType;
}

- (CLActivityType)activityType {
return self.locationManager.activityType;
}

- (void)dismissHeadingCalibrationDisplay {
[self.locationManager dismissHeadingCalibrationDisplay];
}

- (void)requestAlwaysAuthorization {
[self.locationManager requestAlwaysAuthorization];
}

- (void)requestWhenInUseAuthorization {
[self.locationManager requestWhenInUseAuthorization];
}

- (void)startUpdatingHeading {
[self.locationManager startUpdatingHeading];
}

- (void)startUpdatingLocation {
[self.locationManager startUpdatingLocation];
}

- (void)stopUpdatingHeading {
[self.locationManager stopUpdatingHeading];
}

- (void)stopUpdatingLocation {
[self.locationManager stopUpdatingLocation];
}

- (void)dealloc
{
[self.locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingHeading];
self.locationManager.delegate = nil;
self.delegate = nil;
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
[self.delegate locationManager:self didUpdateLocations:locations];
}
}

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateHeading:)]) {
[self.delegate locationManager:self didUpdateHeading:newHeading];
}
}

- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager {
if ([self.delegate respondsToSelector:@selector(locationManagerShouldDisplayHeadingCalibration:)]) {
return [self.delegate locationManagerShouldDisplayHeadingCalibration:self];
}

return NO;
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if ([self.delegate respondsToSelector:@selector(locationManager:didFailWithError:)]) {
[self.delegate locationManager:self didFailWithError:error];
}
}

@end
5 changes: 5 additions & 0 deletions platform/darwin/src/MGLLocationManager_Private.h
@@ -0,0 +1,5 @@
#import "MGLLocationManager.h"

@interface MGLCLLocationManager : NSObject<MGLLocationManager>

@end
4 changes: 4 additions & 0 deletions platform/ios/CHANGELOG.md
Expand Up @@ -4,8 +4,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT

## master

### Other changes

* Fixed a crash that occurred when the user started a gesture before the drift animation for a previous gesture was complete. ([#12148](https://github.com/mapbox/mapbox-gl-native/pull/12148))
* Token string syntax (`"{token}"`) in `MGLSymbolStyleLayer` `text` and `iconImageName` properties is now correctly converted to the appropriate `NSExpression` equivalent. ([#11659](https://github.com/mapbox/mapbox-gl-native/issues/11659))
* Added an `MGLMapView.locationManager` property and `MGLLocationManager` protocol for tracking user location using a custom alternative to `CLLocationManager`. ([#12013](https://github.com/mapbox/mapbox-gl-native/pull/12013))


## 4.2.0 - July 18, 2018

Expand Down
5 changes: 5 additions & 0 deletions platform/ios/app/MBXCustomLocationViewController.h
@@ -0,0 +1,5 @@
#import <UIKit/UIKit.h>

@interface MBXCustomLocationViewController : UIViewController

@end