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

Commit 2de0a35

Browse files
committed
[core] [iOS] Completion handlers for animated methods
Added transition frame and finish functions to CameraOptions. Added Objective-C equivalents to the three main entry points to easeTo() in MGLMapView. Fixes #1581.
1 parent e3992c4 commit 2de0a35

File tree

5 files changed

+85
-6
lines changed

5 files changed

+85
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Known issues:
2323

2424
## iOS master
2525

26+
- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090))
2627
- Fixed an issue preventing the compass from responding to taps after the compass is moved programmatically. ([#3117](https://github.com/mapbox/mapbox-gl-native/pull/3117))
2728

2829
## iOS 3.0.0

include/mbgl/ios/MGLMapView.h

+25
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ IB_DESIGNABLE
134134
* @param animated Specify `YES` if you want the map view to animate scrolling, zooming, and rotating to the new location or `NO` if you want the map to display the new location immediately. */
135135
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated;
136136

137+
/** Changes the center coordinate, zoom level, and direction of the map, calling a completion handler at the end of an optional animation.
138+
* @param centerCoordinate The new center coordinate for the map.
139+
* @param zoomLevel The new zoom level for the map.
140+
* @param direction The new direction for the map, measured in degrees relative to true north.
141+
* @param animated Specify `YES` if you want the map view to animate scrolling, zooming, and rotating to the new location or `NO` if you want the map to display the new location immediately.
142+
* @param completion The block executed after the animation finishes. */
143+
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion;
144+
137145
/** The coordinate bounds visible in the receiver’s viewport.
138146
*
139147
* Changing the value of this property updates the receiver immediately. If you want to animate the change, call `setVisibleCoordinateBounds:animated:` instead. */
@@ -157,6 +165,16 @@ IB_DESIGNABLE
157165
* @param animated Specify `YES` to animate the change by smoothly scrolling and zooming or `NO` to immediately display the given bounds. */
158166
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated;
159167

168+
/** Changes the receiver’s viewport to fit all of the given coordinates and optionally some additional padding on each side.
169+
* @param coordinates The coordinates that the viewport will show.
170+
* @param count The number of coordinates. This number must not be greater than the number of elements in `coordinates`.
171+
* @param insets The minimum padding (in screen points) that will be visible around the given coordinate bounds.
172+
* @param direction The direction to rotate the map to, measured in degrees relative to true north.
173+
* @param duration The duration to animate the change in seconds.
174+
* @param function The timing function to animate the change.
175+
* @param completion The block executed after the animation finishes. */
176+
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;
177+
160178
/** Sets the visible region so that the map displays the specified annotations.
161179
*
162180
* Calling this method updates the value in the visibleCoordinateBounds property and potentially other properties to reflect the new map region.
@@ -193,6 +211,13 @@ IB_DESIGNABLE
193211
* @param function A timing function used for the animation. Set this parameter to `nil` for a transition that matches most system animations. If the duration is `0`, this parameter is ignored. */
194212
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function;
195213

214+
/** Moves the viewpoint to a different location with respect to the map with an optional transition duration and timing function.
215+
* @param camera The new viewpoint.
216+
* @param duration The amount of time, measured in seconds, that the transition animation should take. Specify `0` to jump to the new viewpoint instantaneously.
217+
* @param function A timing function used for the animation. Set this parameter to `nil` for a transition that matches most system animations. If the duration is `0`, this parameter is ignored.
218+
* @param completion The block to execute after the animation finishes. */
219+
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;
220+
196221
#pragma mark - Converting Map Coordinates
197222

198223
/** @name Converting Map Coordinates */

include/mbgl/map/camera.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <mbgl/util/chrono.hpp>
88
#include <mbgl/util/unitbezier.hpp>
99

10+
#include <functional>
11+
1012
namespace mbgl {
1113

1214
struct CameraOptions {
@@ -16,6 +18,8 @@ struct CameraOptions {
1618
mapbox::util::optional<double> pitch;
1719
mapbox::util::optional<Duration> duration;
1820
mapbox::util::optional<mbgl::util::UnitBezier> easing;
21+
std::function<void(double)> transitionFrameFn;
22+
std::function<void()> transitionFinishFn;
1923
};
2024

2125
}

platform/ios/MGLMapView.mm

+46-6
Original file line numberDiff line numberDiff line change
@@ -1565,14 +1565,18 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(
15651565
[self setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:self.direction animated:animated];
15661566
}
15671567

1568-
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
1568+
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated {
1569+
[self setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated completionHandler:NULL];
1570+
}
1571+
1572+
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion
15691573
{
15701574
self.userTrackingMode = MGLUserTrackingModeNone;
15711575

1572-
[self _setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated];
1576+
[self _setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated completionHandler:completion];
15731577
}
15741578

1575-
- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
1579+
- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion
15761580
{
15771581
_mbglMap->cancelTransitions();
15781582

@@ -1589,6 +1593,17 @@ - (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:
15891593
options.duration = durationInSeconds(duration);
15901594
options.easing = MGLUnitBezierForMediaTimingFunction(nil);
15911595
}
1596+
if (completion)
1597+
{
1598+
options.transitionFinishFn = [completion]() {
1599+
// Must run asynchronously after the transition is completely over.
1600+
// Otherwise, a call to -setCenterCoordinate: within the completion
1601+
// handler would reenter the completion handler’s caller.
1602+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
1603+
completion();
1604+
});
1605+
};
1606+
}
15921607
_mbglMap->easeTo(options);
15931608

15941609
[self unrotateIfNeededAnimated:animated];
@@ -1679,7 +1694,11 @@ - (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUIn
16791694
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
16801695
}
16811696

1682-
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
1697+
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function {
1698+
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:NULL];
1699+
}
1700+
1701+
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
16831702
{
16841703
_mbglMap->cancelTransitions();
16851704

@@ -1702,6 +1721,14 @@ - (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUIn
17021721
options.duration = durationInSeconds(duration);
17031722
options.easing = MGLUnitBezierForMediaTimingFunction(function);
17041723
}
1724+
if (completion)
1725+
{
1726+
options.transitionFinishFn = [completion]() {
1727+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
1728+
completion();
1729+
});
1730+
};
1731+
}
17051732
_mbglMap->easeTo(options);
17061733
[self didChangeValueForKey:@"visibleCoordinateBounds"];
17071734

@@ -1815,7 +1842,12 @@ - (void)setCamera:(MGLMapCamera *)camera animated:(BOOL)animated
18151842
[self setCamera:camera withDuration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
18161843
}
18171844

1818-
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
1845+
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function
1846+
{
1847+
[self setCamera:camera withDuration:duration animationTimingFunction:function completionHandler:NULL];
1848+
}
1849+
1850+
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
18191851
{
18201852
_mbglMap->cancelTransitions();
18211853

@@ -1880,6 +1912,14 @@ - (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration a
18801912
options.duration = durationInSeconds(duration);
18811913
options.easing = MGLUnitBezierForMediaTimingFunction(function);
18821914
}
1915+
if (completion)
1916+
{
1917+
options.transitionFinishFn = [completion]() {
1918+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
1919+
completion();
1920+
});
1921+
};
1922+
}
18831923
_mbglMap->easeTo(options);
18841924
}
18851925

@@ -2675,7 +2715,7 @@ - (void)locationManager:(__unused CLLocationManager *)manager didUpdateLocations
26752715
{
26762716
// at sufficient detail, just re-center the map; don't zoom
26772717
//
2678-
[self _setCenterCoordinate:self.userLocation.location.coordinate zoomLevel:self.zoomLevel direction:course animated:YES];
2718+
[self _setCenterCoordinate:self.userLocation.location.coordinate zoomLevel:self.zoomLevel direction:course animated:YES completionHandler:NULL];
26792719
}
26802720
else
26812721
{

src/mbgl/map/transform.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
262262
state.angle = angle;
263263
state.pitch = pitch;
264264

265+
if (options.transitionFinishFn) {
266+
options.transitionFinishFn();
267+
}
265268
view.notifyMapChange(MapChangeRegionDidChange);
266269
} else {
267270
view.notifyMapChange(MapChangeRegionWillChangeAnimated);
@@ -291,6 +294,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
291294
state.pitch = util::interpolate(startP, pitch, t);
292295
// At t = 1.0, a DidChangeAnimated notification should be sent from finish().
293296
if (t < 1.0) {
297+
if (options.transitionFrameFn) {
298+
options.transitionFrameFn(t);
299+
}
294300
view.notifyMapChange(MapChangeRegionIsChanging);
295301
}
296302
return update;
@@ -299,6 +305,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
299305
state.panning = false;
300306
state.scaling = false;
301307
state.rotating = false;
308+
if (options.transitionFinishFn) {
309+
options.transitionFinishFn();
310+
}
302311
view.notifyMapChange(MapChangeRegionDidChangeAnimated);
303312
}, *easeOptions.duration);
304313
}

0 commit comments

Comments
 (0)