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

[ios] Fixes an issue that caused the ornaments ignore contentInset property. #15584

Merged
merged 7 commits into from
Oct 5, 2019

Conversation

fabian-guerra
Copy link
Contributor

@fabian-guerra fabian-guerra commented Sep 7, 2019

This PR Fixes the following issues:

#14827 due to the fact that each bug fix adds its corresponding tests.
#12143 Removes the dependency of the now deprecated UIViewController. automaticallyAdjustsScrollViewInsets.

Tasks:

  • Fixes ornaments placement when automaticallyAdjustContentInset is set to YES and the contentInset is different from the safeArea.
    The property automaticallyAdjustsScrollViewInsets it's been deprecated and moved to UIScrollView the fix I made adds automaticallyAdjustContentInset as part of the mapView that will control this behavior. If set to YES the contentInset will be equal to the view's safeArea (on iOS 11+) or top/bottom layout guides (iOS < 11) if set to NO it will use any value as long as it's not negative.
  • Fix an issue with the camera persisting edgePadding.

@fabian-guerra fabian-guerra added bug iOS Mapbox Maps SDK for iOS needs changelog Indicates PR needs a changelog entry prior to merging. labels Sep 7, 2019
@fabian-guerra fabian-guerra added this to the release-ristretto milestone Sep 7, 2019
@fabian-guerra fabian-guerra self-assigned this Sep 7, 2019
Copy link
Contributor

@astojilj astojilj left a comment

Choose a reason for hiding this comment

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

Comments to reconsider related to API design. Tests looks good.

Fixes #12827

Is the reference wrong?

One more thing to reconsider:
If making new property, why not making it align more to what we have in Android. Following the frequent iOS API changes related to content inset and trying to mimic it in our SDK turned out to be an expensive maintenance effort. How about deprecating current in favour of common API with Android?

The default value of this property is `YES`.

*/
@property (assign) BOOL automaticallyAdjustContentInset;
Copy link
Contributor

@astojilj astojilj Sep 9, 2019

Choose a reason for hiding this comment

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

Let's reconsider using existing contentInsetAdjustmentBehavior instead of adding new property.

@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES

Copy link
Contributor

@friedbunny friedbunny Sep 9, 2019

Choose a reason for hiding this comment

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

Yes, please — this would address #12143. Note that contentInsetAdjustmentBehavior is iOS 11+, so we will still need to support both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@astojilj @friedbunny automaticallyAdjustsScrollViewInsets is a property that belongs to a controller which all views are added to. If we use the UIScrollViews version then we will consider that property only if the root view of a mapView is a scrollView which may not be the case.

It is a problem using an Apple SDK property to control the behavior of the map's sdk because we can't add a proper deprecation notice for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my comment https://github.com/mapbox/mapbox-gl-native/pull/15584/files#r322363031 I stated why using the API described in https://github.com/mapbox/mapbox-gl-native/pull/15584/files#r322082400 is not feasible.

I am keeping the property, and supporting the previous automaticallyAdjustsScrollViewInsets

Copy link
Contributor

Choose a reason for hiding this comment

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

Rename this property to automaticallyAdjustsContentInset, so it looks like a property rather than an action method.

Copy link
Contributor

Choose a reason for hiding this comment

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

The new UIScrollView property’s type is an enumeration rather than a Boolean. Do we anticipate adding more possible values in the future?

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 new UIScrollView property’s type is an enumeration rather than a Boolean. Do we anticipate adding more possible values in the future?

@1ec5 no, do you have in mind any use case that will require an enumeration instead?

// This map view is an immediate child of a view controller’s content view.
viewController = (UIViewController *)self.superview.nextResponder;
}
adjustedContentInsets = self.safeAreaInsets;
Copy link
Contributor

Choose a reason for hiding this comment

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

https://developer.apple.com/documentation/uikit/uiscrollview/2902259-adjustedcontentinset?language=objc

adjustedContentInset:

Use this property to obtain the adjusted area in which to draw content. The contentInsetAdjustmentBehavior property determines whether the safe area insets are included in the adjustment. The safe area insets are then added to the values in the contentInset property to obtain the final value of this property.

Is it different from expected, that we are not adding contentInset to safeAreaInsets but storing adjustedContentInsets (including SafeArea) to contentInsets?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This variable has no relation with the one from the official api. The method adjustContentInset resizes the mapView accordingly to events such as rotation or view changes, this variable is used to calculate those changes and set the new contentInsets. When automaticallyAdjustContentInset or the previous automaticallyAdjustsScrollViewInsets is set to YES then it will calculate the safe area which on iOS 11+ is easier.

Copy link
Contributor

Choose a reason for hiding this comment

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

L1031: safeArea is stored to contentInset, which looks like violating quoted documentation above.

contentInset has relation to official UIScrollView but it might be simpler if not having, let's rename it to padding and keep in sync with Android - certainly simpler then trying to mimic all the iOS scroll view API and maintain it after every release change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

contentInset was meant to behave like the property in UIViewController that's why I'm not violating any feature.


if ( ! viewController.automaticallyAdjustsScrollViewInsets)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is breaking change for people using automaticallyAdjustsScrollViewInsets.
We are not replacing it by contentInsetAdjustmentBehavior that documentation suggests:

@Property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES

Just a comment to reconsider if releasing this in minor release.

Copy link
Contributor

Choose a reason for hiding this comment

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

Indeed — we need to keep supporting automaticallyAdjustsScrollViewInsets, especially for apps that have a minimum deployment version lower than iOS 11.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any ideas on how to signal that we will not use this variable?

Copy link
Contributor

@friedbunny friedbunny Sep 9, 2019

Choose a reason for hiding this comment

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

It’s a semver major change if we stop, so that’s not really an option right now. When a developer hits this code path, it could emit a console warning once that tells them we’re deprecating support for this.

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 added the warning.

Copy link
Contributor

Choose a reason for hiding this comment

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

Has @friedbunny's server concern here been addressed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@julianrex yes we are supporting both properties and logging a warning.

@@ -1015,6 +1033,12 @@ - (void)setContentInset:(UIEdgeInsets)contentInset animated:(BOOL)animated

- (void)setContentInset:(UIEdgeInsets)contentInset animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion
{
// makes sure the insets don't have negative values that could hide the ornaments
// thus violating our ToS
contentInset = UIEdgeInsetsMake(fmaxf(contentInset.top, 0),
Copy link
Contributor

Choose a reason for hiding this comment

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

this is diverging from iOS contentInset - negative values are allowed in contentInset. How about fixing ornaments positioning (clamping position to visible content area) somewhere else or documenting the change here, too.

XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset));
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.latitude, center.latitude, 0.01);
XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.longitude, center.longitude, 0.01);
CGPoint shiftedPoint = [self.mapView convertCoordinate:center toPointToView:self.mapView];
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good.

@fabian-guerra
Copy link
Contributor Author

@astojilj yes is wrong, fixed the reference. Thanks.

adjustedContentInsets = self.safeAreaInsets;

} else {
adjustedContentInsets.top = viewController.topLayoutGuide.length;
Copy link
Contributor

@astojilj astojilj Sep 10, 2019

Choose a reason for hiding this comment

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

Is this part is working properly also for >= 11?
If it is, let's have one implementation and avoidDependency to safeArea.

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.

Remember to add a changelog entry about the behaviors that changed and the new property.

Are any of these changes relevant to macOS? If so, could you make the corresponding changes or ticket that out as tail work? I’d like to keep the two implementations as close as possible; the introduction of this new property should actually help with that. Thanks!

@@ -3798,6 +3875,27 @@ - (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edg
return [self cameraForCameraOptions:cameraOptions];
}

- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinate:(CLLocationCoordinate2D)coordinate edgePadding:(UIEdgeInsets)insets {
Copy link
Contributor

Choose a reason for hiding this comment

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

This method seems to be unused?

self.contentInset.right - self.safeMapViewContentInsets.right);

// makes sure the insets don't have negative values that could hide the ornaments
// thus violating our ToS
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, hadn’t considered that possibility before.

When the map view’s superview is an instance of `UIViewController` whose
`automaticallyAdjustsScrollViewInsets` property is `YES`, the value of this
property may be overridden at any time.

The usage of `automaticallyAdjustsScrollViewInsets` it is been deprecated
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Split this into two sentences and replace “it is been” with “has been”. (×3)


// TODO: This warning should be removed when automaticallyAdjustsScrollViewInsets is removed from
// the UIViewController api.
NSLog(@"%@ WARNING UIViewController.automaticallyAdjustsScrollViewInsets is deprecated use MGLMapView.automaticallyAdjustContentInset instead.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this log message be guarded by a dispatch_once, or is repetition desirable in this case?

When the map view’s superview is an instance of `UIViewController` whose
`automaticallyAdjustsScrollViewInsets` property is `YES`, the value of this
property may be overridden at any time.

The usage of `automaticallyAdjustsScrollViewInsets` it is been deprecated
use the map view’s property `automaticallyAdjustContentInset`instead.
Copy link
Contributor

Choose a reason for hiding this comment

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

“Use the MGLMapView.automaticallyAdjustsContentInset property instead.”

The default value of this property is `YES`.

*/
@property (assign) BOOL automaticallyAdjustContentInset;
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename this property to automaticallyAdjustsContentInset, so it looks like a property rather than an action method.

The default value of this property is `YES`.

*/
@property (assign) BOOL automaticallyAdjustContentInset;
Copy link
Contributor

Choose a reason for hiding this comment

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

The new UIScrollView property’s type is an enumeration rather than a Boolean. Do we anticipate adding more possible values in the future?

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.

Looks good - just the questions below.


// TODO: This warning should be removed when automaticallyAdjustsScrollViewInsets is removed from
// the UIViewController api.
NSLog(@"%@ WARNING UIViewController.automaticallyAdjustsScrollViewInsets is deprecated use MGLMapView.automaticallyAdjustContentInset instead.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Use MGLLogInfo 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.

We want the warning logged into the console directly using our logging framework can't warranty that.

automaticallyAdjustContentInset = viewController.automaticallyAdjustsScrollViewInsets;
}

if (! automaticallyAdjustContentInset) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be if (automaticallyAdjustContentInset)?

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 I had an else option it would be. In this case I will subtract the safe areas only if automaticallyAdjustContentInset is NO

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clarifying, I had misread the - for a + 😄


if ( ! viewController.automaticallyAdjustsScrollViewInsets)
Copy link
Contributor

Choose a reason for hiding this comment

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

Has @friedbunny's server concern here been addressed?

@fabian-guerra fabian-guerra removed the needs changelog Indicates PR needs a changelog entry prior to merging. label Oct 3, 2019
Fixed an issue that caused ornaments ignore the contentInset. Added a new property automaticallyAdjustContentInset that has the same purpose as UIViewController. automaticallyAdjustsScrollViewInsets. This was changed due to the latter being deprecated.
The property automaticallyAdjustsScrollViewInsets overrode automaticallyAdjustsScrollViewInsets which caused a breaking change. This is fixed to consider the legacy property when calculating the content insets and added tests for both cases.
Fixed an issue that caused a discrepancy between the contentInset in MGLMapView and the padding in the transformation state.

When padding is passed through methods such as setCamera it’s persisted. This fix resets the contentInsets.
@fabian-guerra fabian-guerra merged commit 5c565a5 into master Oct 5, 2019
@fabian-guerra fabian-guerra deleted the fabian-insets-14827 branch October 5, 2019 00:13
@astojilj
Copy link
Contributor

astojilj commented Oct 6, 2019

@fabian-guerra Sorry for late review. Was this patch verified against the latest version of navigation-ios including the mapbox/mapbox-navigation-ios#2211 patch, on both iOS device and CarPlay?

cc @1ec5

@fabian-guerra
Copy link
Contributor Author

@astojilj no. We fixed other content insets issues and decided that the issue affecting navigation will be addressed on a SEMVER.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants