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

[ios] Add delegate method to specify the user location annotation’s position #12907

Merged
merged 1 commit into from
Oct 2, 2018

Conversation

captainbarbosa
Copy link
Contributor

@captainbarbosa captainbarbosa commented Sep 17, 2018

This PR makes three changes:

@captainbarbosa captainbarbosa added iOS Mapbox Maps SDK for iOS ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold labels Sep 17, 2018
@captainbarbosa captainbarbosa added this to the ios-v4.5.0 milestone Sep 17, 2018
@captainbarbosa captainbarbosa self-assigned this Sep 17, 2018
@@ -416,7 +416,7 @@ MGL_EXPORT IB_DESIGNABLE
transition. If you don’t want to animate the change, use the
`-setUserLocationVerticalAlignment:animated:` method instead.
*/
@property (nonatomic, assign) MGLAnnotationVerticalAlignment userLocationVerticalAlignment;
@property (nonatomic, assign) MGLAnnotationVerticalAlignment userLocationVerticalAlignment __attribute__((deprecated("Use -userLocationAnchorForMapView delegate method instead.")));
Copy link
Contributor

Choose a reason for hiding this comment

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

Qualify the method name with the protocol name for discoverability.


@param mapView The map view that is tracking the user's location.
*/
- (CGPoint)userLocationAnchorForMapView:(MGLMapView *)mapView;
Copy link
Contributor

Choose a reason for hiding this comment

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

By convention, the first selector part begins with the first parameter’s type. If the return type is a CGPoint, describe it as an “anchor point” rather than an “anchor”, which typically describes an NSLayoutAnchor. Thus: -mapViewUserLocationAnchor:.

@@ -308,6 +308,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView didChangeUserTrackingMode:(MGLUserTrackingMode)mode animated:(BOOL)animated;

/**
Returns a CGPoint value to offset the user location annotation, relative to
the camera's center coordinate.
Copy link
Contributor

Choose a reason for hiding this comment

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

A screen point can only be relative to another screen point, not a geographic coordinate. I think the intention is to say that it’s relative to the center of the map view. Note that the navigation SDK’s analogous NavigationMapViewDelegate.navigationMapViewUserAnchorPoint(_:) method is expressed relative to the map view’s origin, not its center. There are pros and cons to either approach, so it’s good that the frame of reference is being called out here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A screen point can only be relative to another screen point, not a geographic coordinate.

Does this mean the camera's center can also relate to a CGPoint instead of a coordinate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I'm going to base my implementation off of the map view's origin as well, to keep things consistent with the implementation in the Navigation SDK.

{
// Get whatever value is returned from the delegate method that responds to
// the selector and assign it to the center
center = [self.delegate userLocationAnchorForMapView:self];
Copy link
Contributor

Choose a reason for hiding this comment

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

This line sets center from scratch, effectively making it relative to the origin rather than the view’s center, which is stored in center up to this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we choose to set the anchor point based off the the origin, should we adjust the original center (CGPointMake(CGRectGetMidX(contentFrame), CGRectGetMidY(contentFrame))) to do the same?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, because the legacy userLocationVerticalAlignment code depends on that initial value, whereas the new -mapViewUserLocationAnchorPoint: code does not.


if ([self.delegate respondsToSelector:@selector(mapViewUserLocationAnchorPoint:)])
{
center = [self.delegate mapViewUserLocationAnchorPoint:self];
Copy link
Contributor

Choose a reason for hiding this comment

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

The delegate should be expressing the anchor point in relation to the content frame, so offset the anchor point by the content insets.

{
// Get whatever value is returned from the delegate method that responds to
// the selector and assign it to the center
center = [self.delegate userLocationAnchorForMapView:self];
Copy link
Contributor

Choose a reason for hiding this comment

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

No, because the legacy userLocationVerticalAlignment code depends on that initial value, whereas the new -mapViewUserLocationAnchorPoint: code does not.

@@ -310,7 +310,7 @@ NS_ASSUME_NONNULL_BEGIN

/**
Returns a CGPoint value to offset the user location annotation, relative to
the the map view's origin.
the the map view's content insets.
Copy link
Contributor

Choose a reason for hiding this comment

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

relative to the map view’s origin after applying the map view’s content insets.

@@ -5997,7 +5997,8 @@ - (CGPoint)userLocationAnnotationViewCenter

if ([self.delegate respondsToSelector:@selector(mapViewUserLocationAnchorPoint:)])
{
center = [self.delegate mapViewUserLocationAnchorPoint:self];
CGPoint anchorPoint = [self.delegate mapViewUserLocationAnchorPoint:self];
center = CGPointMake((contentFrame.origin.x + anchorPoint.x), (contentFrame.origin.y + anchorPoint.y));
Copy link
Contributor

Choose a reason for hiding this comment

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

By this point, contentFrame has already been inset by -edgePaddingForFollowingWithCourse, which might not be quite correct. That method does account for the size of the puck, which is probably a good thing, but it also applies MGLUserLocationAnnotationViewInset.

@1ec5 1ec5 added the navigation For the Mapbox Navigation SDK for Android or iOS or navigation use cases in general label Sep 25, 2018
@1ec5
Copy link
Contributor

1ec5 commented Sep 26, 2018

An idea for an integration test:

  1. Create a map view with a specific frame.
  2. Set the map view’s content insets.
  3. Configure a custom location manager that immediately feeds the map view a specific coordinate.
  4. Set the map view’s userTrackingMode without animation.
  5. Get the user location annotation view and check its frame.

@captainbarbosa captainbarbosa force-pushed the user-location-delegate-method branch 3 times, most recently from eb690a0 to 53b6b47 Compare October 1, 2018 20:47
@captainbarbosa
Copy link
Contributor Author

I think this is ready for a preliminary review 👀

Copy link
Contributor

@julianrex julianrex left a comment

Choose a reason for hiding this comment

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

Is there a branch where I can check this out in iosapp?


@synthesize delegate;

- (instancetype)init
Copy link
Contributor

Choose a reason for hiding this comment

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

This init method isn't needed here since it doesn't do anything in addition to super.

return self;
}

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

Choose a reason for hiding this comment

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

Since this is a test manager, how about returning kCLAuthorizationStatusAuthorized here?

@captainbarbosa captainbarbosa force-pushed the user-location-delegate-method branch from d6be976 to 664a3ba Compare October 2, 2018 20:40
@captainbarbosa
Copy link
Contributor Author

@julianrex Here's a branch you can use to test this out in iosapp: https://github.com/mapbox/mapbox-gl-native/tree/user-location-delegate-demo

@captainbarbosa captainbarbosa force-pushed the user-location-delegate-method branch from 664a3ba to e267524 Compare October 2, 2018 20:42
@captainbarbosa captainbarbosa removed the ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold label Oct 2, 2018
@captainbarbosa captainbarbosa force-pushed the user-location-delegate-method branch from e267524 to 6dc7d5b Compare October 2, 2018 21:27
@captainbarbosa
Copy link
Contributor Author

Rebased on master & added changelog entry.

@@ -308,6 +308,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView didChangeUserTrackingMode:(MGLUserTrackingMode)mode animated:(BOOL)animated;

/**
Returns a CGPoint value to offset the user location annotation, relative to the
Copy link
Contributor

Choose a reason for hiding this comment

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

CGPoint is already present in the declaration, so I’d maybe describe it here in lay terms. It’s an absolute screen coordinate, not an offset (which would be CGVector):

Returns a screen coordinate at which to position the user location annotation…

map view’s origin after applying the map view’s content insets.

This method will offset the user location annotation by the specified
X and Y values determined by the CGPoint.
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the default behavior when this method goes unimplemented? How does this method interact with the MGLMapView.userLocationVerticalAlignment property when it is set and this method is also implemented?

@@ -11,6 +11,11 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed a crash when a style layer `*-pattern` property evaluates to nil for a particular feature. ([#12896](https://github.com/mapbox/mapbox-gl-native/pull/12896))
* Fixed an issue with view annotations (including the user location annotation) and the GL map lagging relative to each other. ([#12895](https://github.com/mapbox/mapbox-gl-native/pull/12895))

### User location
* Added `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` to offset the user location annotation with a custom `CGPoint`. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
Copy link
Contributor

Choose a reason for hiding this comment

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

…to customize the location of the user location annotation.

### User location
* Added `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` to offset the user location annotation with a custom `CGPoint`. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Marked `-[MGLMapView setUserLocationVerticalAlignment:]` as deprecated. Use `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` instead. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Added `-[MGLMapView updateUserLocationAnnotationView]` and `-[MGLMapView updateUserLocationAnnotationView:animated:]` to public API to update the position of the user location annotation. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as the user is concerned, these methods never existed in the first place, so “to public API” is redundant.

Added the -[MGLMapView updateUserLocationAnnotationView] and -[MGLMapView updateUserLocationAnnotationView:animated:] methods to update the position of the user location annotation between location updates.

Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

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

Good to merge once the documentation feedback in #12907 (review) is addressed.

…osition

Update method name

More API drafting

Add deprecation flag

Add Swift delegate integration test

Update method name and documentation

Update deprecation notices

Update method name

Offset anchor point relative to contentFrame

Update docs

Only run through switch statement if delegate is unimplemented

Account for content inset + refactor logic

Adjust edgePaddingForFollowing

Fix Swift delegate integration test

Set up integration test

Set up test location manager

.

Remove unused file reference from test

Return CGPoint value from delegate method within integration test setup

Test anchor points

Make updateUserLocationAnnotationView public

Refactor test

Update test location manager

Changelog entry

Doc fixes
@captainbarbosa captainbarbosa force-pushed the user-location-delegate-method branch from 6dc7d5b to db1d530 Compare October 2, 2018 22:02
@captainbarbosa captainbarbosa merged commit 7b24339 into master Oct 2, 2018
@captainbarbosa captainbarbosa deleted the user-location-delegate-method branch October 2, 2018 22:28
* Added `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` to customize the position of the user location annotation.. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Marked `-[MGLMapView setUserLocationVerticalAlignment:]` as deprecated. Use `-[MGLMapViewDelegate mapViewUserLocationAnchorPoint:]` instead. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Added the `-[MGLMapView updateUserLocationAnnotationView]` and `-[MGLMapView updateUserLocationAnnotationView:animated:]` methods to update the position of the user location annotation between location updates. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907))
* Fixed an issue where the user location annotation was positioned incorrectly when the map view had a left or right content inset. ([#12907](https://github.com/mapbox/mapbox-gl-native/pull/12907)) inset
Copy link
Contributor

Choose a reason for hiding this comment

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

There’s an extra “inset” at the end of this sentence.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
iOS Mapbox Maps SDK for iOS navigation For the Mapbox Navigation SDK for Android or iOS or navigation use cases in general
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants