summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2018-02-13 11:40:40 -0500
committerFabian Guerra <fabian.guerra@mapbox.com>2018-02-13 11:40:40 -0500
commitb68266953fab505ad257c7ab471a75eb9bd634bc (patch)
tree0fb029e6b2a967a678a69993bd0e018291143f92
parent44ca0a5ec4979138514e8dda10dd1b1173dd0db1 (diff)
parent3a0c87b1b4d4f2789a2ca5e995a79a7bad4f761f (diff)
downloadqtlocation-mapboxgl-b68266953fab505ad257c7ab471a75eb9bd634bc.tar.gz
Merge tag 'ios-v3.7.4' into master
# Conflicts: # include/mbgl/style/conversion/tileset.hpp # include/mbgl/util/tileset.hpp # platform/android/CHANGELOG.md # platform/android/MapboxGLAndroidSDK/gradle.properties # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java # platform/ios/CHANGELOG.md # platform/ios/ios.xcodeproj/project.pbxproj # platform/macos/CHANGELOG.md # src/mbgl/layout/symbol_projection.cpp # src/mbgl/renderer/tile_pyramid.cpp # src/mbgl/style/conversion/tileset.cpp
-rw-r--r--platform/android/MapboxGLAndroidSDK/proguard-rules.pro5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml7
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm339
-rw-r--r--platform/ios/CHANGELOG.md8
-rw-r--r--platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK-symbols.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK.podspec2
-rw-r--r--platform/ios/app/MBXSnapshotsViewController.m3
-rw-r--r--platform/ios/app/MBXViewController.m4
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj41
-rw-r--r--platform/ios/src/MGLCameraChangeReason.h61
-rw-r--r--platform/ios/src/MGLLocationManager.m6
-rw-r--r--platform/ios/src/MGLMapView.mm178
-rw-r--r--platform/ios/src/MGLMapViewDelegate.h119
-rw-r--r--platform/ios/src/MGLMapboxEvents.m3
-rw-r--r--platform/ios/src/MGLTelemetryConfig.h18
-rw-r--r--platform/ios/src/MGLTelemetryConfig.m35
-rw-r--r--platform/ios/test/MGLMapViewDelegateIntegrationTests.swift11
-rw-r--r--platform/ios/uitest/MapViewTests.m7
-rw-r--r--platform/macos/CHANGELOG.md5
22 files changed, 638 insertions, 280 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
index b5a1d82c81..3b8adac5a8 100644
--- a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
@@ -12,4 +12,7 @@
# config for okhttp 3.8.0, https://github.com/square/okhttp/pull/3354
-dontwarn okio.**
-dontwarn javax.annotation.Nullable
--dontwarn javax.annotation.ParametersAreNonnullByDefault \ No newline at end of file
+-dontwarn javax.annotation.ParametersAreNonnullByDefault
+
+# config for optional location provider https://github.com/mapbox/mapbox-gl-native/issues/10960
+-dontwarn com.mapzen.android.lost.api** \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 03a1d949f4..d2567a114b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -42,18 +42,16 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import timber.log.Timber;
-
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;
@@ -137,17 +135,7 @@ public class MapView extends FrameLayout {
setContentDescription(context.getString(R.string.mapbox_mapActionDescription));
setWillNotDraw(false);
- getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- getViewTreeObserver().removeOnGlobalLayoutListener(this);
- } else {
- getViewTreeObserver().removeGlobalOnLayoutListener(this);
- }
- initialiseDrawingSurface(options);
- }
- });
+ getViewTreeObserver().addOnGlobalLayoutListener(new MapViewLayoutListener(this, options));
}
private void initialiseMap() {
@@ -313,7 +301,7 @@ public class MapView extends FrameLayout {
addView(textureView, 0);
} else {
- GLSurfaceView glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
+ GLSurfaceView glSurfaceView = new GLSurfaceView(getContext());
glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, options.getLocalIdeographFontFamily()) {
@Override
@@ -323,7 +311,7 @@ public class MapView extends FrameLayout {
}
};
- glSurfaceView.setVisibility(View.VISIBLE);
+ addView(glSurfaceView, 0);
}
nativeMapView = new NativeMapView(this, mapRenderer);
@@ -890,6 +878,30 @@ public class MapView extends FrameLayout {
void onMapChanged(@MapChange int change);
}
+ private static class MapViewLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
+
+ private WeakReference<MapView> mapViewWeakReference;
+ private MapboxMapOptions options;
+
+ MapViewLayoutListener(MapView mapView, MapboxMapOptions options) {
+ this.mapViewWeakReference = new WeakReference<>(mapView);
+ this.options = options;
+ }
+
+ @Override
+ public void onGlobalLayout() {
+ MapView mapView = mapViewWeakReference.get();
+ if (mapView != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ } else {
+ mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ }
+ mapView.initialiseDrawingSurface(options);
+ }
+ }
+ }
+
private class FocalPointInvalidator implements FocalPointChangeListener {
private final List<FocalPointChangeListener> focalPointChangeListeners = new ArrayList<>();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
index c34833e9ce..1e76ffe3fb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
@@ -4,7 +4,6 @@ import android.graphics.SurfaceTexture;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.view.TextureView;
-
import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser;
import java.lang.ref.WeakReference;
@@ -219,13 +218,6 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
break;
}
- // Check if the size has changed
- if (sizeChanged) {
- recreateSurface = true;
- sizeChanged = false;
- break;
- }
-
// Reset the request render flag now, so we can catch new requests
// while rendering
requestRender = false;
@@ -273,6 +265,12 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
continue;
}
+ if (sizeChanged) {
+ mapRenderer.onSurfaceChanged(gl, w, h);
+ sizeChanged = false;
+ continue;
+ }
+
// Don't continue without a surface
if (eglHolder.eglSurface == EGL10.EGL_NO_SURFACE) {
continue;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
index df7ccaaca9..29ff49f47e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
@@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <android.opengl.GLSurfaceView
- android:id="@+id/surfaceView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:contentDescription="@null"
- android:visibility="gone"/>
-
<FrameLayout
android:id="@+id/markerViewContainer"
android:layout_width="match_parent"
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index f03bd70c86..11a5442761 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -81,7 +81,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
@end
@interface MGLMapSnapshotter()
-
+@property (nonatomic) BOOL loading;
@end
@implementation MGLMapSnapshotter {
@@ -90,6 +90,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
std::unique_ptr<mbgl::MapSnapshotter> _mbglMapSnapshotter;
std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> _snapshotCallback;
NS_ARRAY_OF(MGLAttributionInfo *) *_attributionInfo;
+
}
- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options
@@ -115,182 +116,192 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
format:@"Already started this snapshotter."];
}
- _loading = true;
+ self.loading = true;
- dispatch_async(queue, ^{
- _snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn) {
- _loading = false;
+ __weak __typeof__(self) weakSelf = self;
+ _snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn) {
+ __typeof__(self) strongSelf = weakSelf;
+ strongSelf.loading = false;
+
+
+ if (mbglError) {
+ NSString *description = @(mbgl::util::toString(mbglError).c_str());
+ NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
+ NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo];
- NSMutableArray *infos = [NSMutableArray array];
-
+ // Dispatch result to origin queue
+ dispatch_async(queue, ^{
+ completion(nil, error);
+ });
+ } else {
#if TARGET_OS_IPHONE
- CGFloat fontSize = [UIFont smallSystemFontSize];
- UIColor *attributeFontColor = [UIColor blackColor];
+ MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:strongSelf.options.scale];
#else
- CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
- NSColor *attributeFontColor = [NSColor blackColor];
+ MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)];
+ mglImage.size = NSMakeSize(mglImage.size.width / strongSelf.options.scale,
+ mglImage.size.height / strongSelf.options.scale);
#endif
- for (auto attribution = attributions.begin(); attribution != attributions.end(); ++attribution) {
- NSString *attributionHTMLString = @(attribution->c_str());
- NSArray *tileSetInfos = [MGLAttributionInfo attributionInfosFromHTMLString:attributionHTMLString
- fontSize:fontSize
- linkColor:attributeFontColor];
- [infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
- }
-
- _attributionInfo = infos;
-
- if (mbglError) {
- NSString *description = @(mbgl::util::toString(mbglError).c_str());
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
- NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo];
-
- // Dispatch result to origin queue
- dispatch_async(queue, ^{
- completion(nil, error);
- });
- } else {
+ [strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn queue:queue completionHandler:completion];
+ }
+ _snapshotCallback = NULL;
+ });
+ dispatch_async(queue, ^{
+ _mbglMapSnapshotter->snapshot(_snapshotCallback->self());
+
+ });
+}
+
+- (MGLImage *)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn queue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion {
+
+ NSMutableArray *infos = [NSMutableArray array];
+
#if TARGET_OS_IPHONE
- MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:self.options.scale];
+ CGFloat fontSize = [UIFont smallSystemFontSize];
+ UIColor *attributeFontColor = [UIColor blackColor];
#else
- MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)];
- mglImage.size = NSMakeSize(mglImage.size.width / self.options.scale,
- mglImage.size.height / self.options.scale);
+ CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
+ NSColor *attributeFontColor = [NSColor blackColor];
#endif
-
- // Process image watermark in a work queue
- dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(workQueue, ^{
+ for (auto attribution = attributions.begin(); attribution != attributions.end(); ++attribution) {
+ NSString *attributionHTMLString = @(attribution->c_str());
+ NSArray *tileSetInfos = [MGLAttributionInfo attributionInfosFromHTMLString:attributionHTMLString
+ fontSize:fontSize
+ linkColor:attributeFontColor];
+ [infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
+ }
+
+ _attributionInfo = infos;
+
+ // Process image watermark in a work queue
+ dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ dispatch_async(workQueue, ^{
#if TARGET_OS_IPHONE
- MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
- for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
- attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
- CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
- if (attributionSize.width <= mglImage.size.width) {
- break;
- }
- }
-
- UIImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
- CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
-
- CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
- CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
- logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
- if (!logoImage) {
- CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
- logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + defaultLogoSize.height), 0, defaultLogoSize.height);
- attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
- }
-
- CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
- attributionOrigin.y,
- attributionBackgroundSize.width,
- attributionBackgroundSize.height);
- CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
- attributionBackgroundFrame.origin.y - 1);
-
- CGRect cropRect = CGRectMake(attributionBackgroundFrame.origin.x * mglImage.scale,
- attributionBackgroundFrame.origin.y * mglImage.scale,
- attributionBackgroundSize.width * mglImage.scale,
- attributionBackgroundSize.height * mglImage.scale);
-
-
- UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
-
- [mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
-
- [logoImage drawInRect:logoImageRect];
-
- UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext();
- CGImageRef attributionImageRef = CGImageCreateWithImageInRect([currentImage CGImage], cropRect);
- UIImage *attributionImage = [UIImage imageWithCGImage:attributionImageRef];
- CGImageRelease(attributionImageRef);
-
- CIImage *ciAttributionImage = [[CIImage alloc] initWithCGImage:attributionImage.CGImage];
-
- UIImage *blurredAttributionBackground = [self blurredAttributionBackground:ciAttributionImage];
-
- [blurredAttributionBackground drawInRect:attributionBackgroundFrame];
-
- [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
-
- UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
-
- UIGraphicsEndImageContext();
+ MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
+ for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
+ attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
+ CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
+ if (attributionSize.width <= mglImage.size.width) {
+ break;
+ }
+ }
+
+ UIImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
+ CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
+
+ CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
+ CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
+ if (!logoImage) {
+ CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
+ logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + defaultLogoSize.height), 0, defaultLogoSize.height);
+ attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
+ }
+
+ CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
+ attributionOrigin.y,
+ attributionBackgroundSize.width,
+ attributionBackgroundSize.height);
+ CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
+ attributionBackgroundFrame.origin.y - 1);
+
+ CGRect cropRect = CGRectMake(attributionBackgroundFrame.origin.x * mglImage.scale,
+ attributionBackgroundFrame.origin.y * mglImage.scale,
+ attributionBackgroundSize.width * mglImage.scale,
+ attributionBackgroundSize.height * mglImage.scale);
+
+
+ UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
+
+ [mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
+
+ [logoImage drawInRect:logoImageRect];
+
+ UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext();
+ CGImageRef attributionImageRef = CGImageCreateWithImageInRect([currentImage CGImage], cropRect);
+ UIImage *attributionImage = [UIImage imageWithCGImage:attributionImageRef];
+ CGImageRelease(attributionImageRef);
+
+ CIImage *ciAttributionImage = [[CIImage alloc] initWithCGImage:attributionImage.CGImage];
+
+ UIImage *blurredAttributionBackground = [self blurredAttributionBackground:ciAttributionImage];
+
+ [blurredAttributionBackground drawInRect:attributionBackgroundFrame];
+
+ [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
+
+ UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
+
+ UIGraphicsEndImageContext();
#else
- NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
- NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
-
- MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
- for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
- attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
- CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
- if (attributionSize.width <= mglImage.size.width) {
- break;
- }
- }
-
- NSImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
- CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
- NSImage *sourceImage = mglImage;
-
- CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
- CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
- MGLLogoImagePosition.y + 1);
- if (!logoImage) {
- CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
- logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, defaultLogoSize.height);
- attributionOrigin = CGPointMake(10, attributionOrigin.y);
- }
-
- CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
- attributionOrigin.y,
- attributionBackgroundSize.width,
- attributionBackgroundSize.height);
- CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
- logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
-
-
- NSImage *compositedImage = nil;
- NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
- context:nil
- hints:nil];
- compositedImage = [[NSImage alloc] initWithSize:targetSize];
-
- [compositedImage lockFocus];
-
- [sourceImageRep drawInRect: targetFrame];
-
- if (logoImage) {
- [logoImage drawInRect:logoImageRect];
- }
-
- NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];
-
- CIImage *attributionBackgroundImage = [[CIImage alloc] initWithCGImage:[attributionBackground CGImage]];
-
- NSImage *blurredAttributionBackground = [self blurredAttributionBackground:attributionBackgroundImage];
-
- [blurredAttributionBackground drawInRect:attributionBackgroundFrame];
-
- [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
-
- [compositedImage unlockFocus];
-
-
-#endif
-
- // Dispatch result to origin queue
- dispatch_async(queue, ^{
- MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage scale:self.options.scale pointForFn:pointForFn];
- completion(snapshot, nil);
- });
- });
+ NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
+ NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
+
+ MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
+ for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
+ attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
+ CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
+ if (attributionSize.width <= mglImage.size.width) {
+ break;
}
+ }
+
+ NSImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
+ CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
+ NSImage *sourceImage = mglImage;
+
+ CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
+ CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
+ MGLLogoImagePosition.y + 1);
+ if (!logoImage) {
+ CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
+ logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, defaultLogoSize.height);
+ attributionOrigin = CGPointMake(10, attributionOrigin.y);
+ }
+
+ CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
+ attributionOrigin.y,
+ attributionBackgroundSize.width,
+ attributionBackgroundSize.height);
+ CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
+
+
+ NSImage *compositedImage = nil;
+ NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
+ context:nil
+ hints:nil];
+ compositedImage = [[NSImage alloc] initWithSize:targetSize];
+
+ [compositedImage lockFocus];
+
+ [sourceImageRep drawInRect: targetFrame];
+
+ if (logoImage) {
+ [logoImage drawInRect:logoImageRect];
+ }
+
+ NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];
+
+ CIImage *attributionBackgroundImage = [[CIImage alloc] initWithCGImage:[attributionBackground CGImage]];
+
+ NSImage *blurredAttributionBackground = [self blurredAttributionBackground:attributionBackgroundImage];
+
+ [blurredAttributionBackground drawInRect:attributionBackgroundFrame];
+
+ [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
+
+ [compositedImage unlockFocus];
+
+
+#endif
+
+ // Dispatch result to origin queue
+ dispatch_async(queue, ^{
+ MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage scale:self.options.scale pointForFn:pointForFn];
+ completion(snapshot, nil);
});
- _mbglMapSnapshotter->snapshot(_snapshotCallback->self());
});
+ return nil;
}
- (void)drawAttributionTextWithStyle:(MGLAttributionInfoStyle)attributionInfoStyle origin:(CGPoint)origin
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 5482b6d5eb..ef27596d2b 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -16,7 +16,6 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Improved the reliability of collision detection between symbols near the edges of tiles, as well as between symbols when the map is tilted. It is no longer necessary to enable `MGLSymbolStyleLayer.symbolAvoidsEdges` to prevent symbols in adjacent tiles from overlapping with each other. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Symbols can fade in and out as the map pans, rotates, or tilts. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
-* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
* Fixed an issue preventing `MGLImageSource`s from drawing on the map when the map is zoomed in and tilted. ([#10677](https://github.com/mapbox/mapbox-gl-native/pull/10677))
@@ -33,7 +32,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Added a Hebrew localization. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967))
* Long-pressing the attribution button causes the SDK’s version number to be displayed in the action sheet that appears. ([#10650](https://github.com/mapbox/mapbox-gl-native/pull/10650))
-## 3.7.3
+## 3.7.4 - February 12, 2018
+
+* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
+* Fixed an issue that caused `-[MGLMapSnapshotter pointForCoordinate:]` to return the wrong point. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
+
+## 3.7.3 - January 10, 2018
* Fixed a crash while zooming while annotations are present on the map. ([#10791](https://github.com/mapbox/mapbox-gl-native/pull/10791))
* CJK characters can be displayed in a locally installed font or a custom font bundled with the application, reducing map download times. Specify the font name using the `MGLIdeographicFontFamilyName` key in the application’s Info.plist file. ([#10522](https://github.com/mapbox/mapbox-gl-native/pull/10522))
diff --git a/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
index fb9511e707..65adcf8d3c 100644
--- a/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.3'
+ version = '3.7.4'
m.name = 'Mapbox-iOS-SDK-nightly-dynamic'
m.version = "#{version}-nightly"
diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
index ea8ae667f6..fff485ebb4 100644
--- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.3'
+ version = '3.7.4'
m.name = 'Mapbox-iOS-SDK-symbols'
m.version = "#{version}-symbols"
diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec
index 1e81272d6d..3181b66918 100644
--- a/platform/ios/Mapbox-iOS-SDK.podspec
+++ b/platform/ios/Mapbox-iOS-SDK.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.3'
+ version = '3.7.4'
m.name = 'Mapbox-iOS-SDK'
m.version = version
diff --git a/platform/ios/app/MBXSnapshotsViewController.m b/platform/ios/app/MBXSnapshotsViewController.m
index 3bf93d8721..95d3251e2e 100644
--- a/platform/ios/app/MBXSnapshotsViewController.m
+++ b/platform/ios/app/MBXSnapshotsViewController.m
@@ -50,12 +50,13 @@
options.zoomLevel = 10;
// Create and start the snapshotter
+ __weak UIImageView *weakImageView = imageView;
MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler: ^(MGLMapSnapshot* snapshot, NSError *error) {
if (error) {
NSLog(@"Could not load snapshot: %@", [error localizedDescription]);
} else {
- imageView.image = snapshot.image;
+ weakImageView.image = snapshot.image;
}
}];
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 0f617188b9..282dc901d6 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -1280,6 +1280,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
- (void)styleDynamicPointCollection
{
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(36.9979, -109.0441) zoomLevel:14 animated:NO];
+
CLLocationCoordinate2D coordinates[] = {
{37.00145594210082, -109.04960632324219},
{37.00173012609867, -109.0404224395752},
@@ -1889,7 +1890,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self updateHUD];
}
-- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
+- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated
+{
[self updateHUD];
}
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index d44fee3430..9614bd009a 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -297,6 +297,12 @@
96E5170320005A6800A02306 /* FABKitProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */; };
96E5170420005A6B00A02306 /* SMCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848891CBB037E00AB86E3 /* SMCalloutView.h */; };
96F3F73C1F57124B003E2D2C /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
+ AC518DFF201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; };
+ AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; };
+ AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
+ AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
+ CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; };
@@ -829,6 +835,9 @@
96E0272D1E57C7E6004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0272E1E57C7E7004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
+ AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = "<group>"; };
+ AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = "<group>"; };
+ CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = "<group>"; };
DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = "<group>"; };
DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = "<group>"; };
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
@@ -1578,19 +1587,20 @@
DA8848331CBAFB2A00AB86E3 /* Kit */ = {
isa = PBXGroup;
children = (
- 355ADFF91E9281C300F3939D /* Views */,
- 35CE617F1D4165C2004F2359 /* Categories */,
DAD165841CF4D06B001FF4B9 /* Annotations */,
+ 35CE617F1D4165C2004F2359 /* Categories */,
+ DA88487F1CBB033F00AB86E3 /* Fabric */,
+ DA8848881CBB036000AB86E3 /* SMCalloutView */,
DAD165851CF4D08B001FF4B9 /* Telemetry */,
+ 355ADFF91E9281C300F3939D /* Views */,
+ CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */,
DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */,
DA704CC11F65A475004B3F28 /* MGLMapAccessibilityElement.mm */,
- DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */,
+ DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
+ DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
- DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
- DA88487F1CBB033F00AB86E3 /* Fabric */,
- DA8848881CBB036000AB86E3 /* SMCalloutView */,
);
name = Kit;
path = src;
@@ -1635,6 +1645,16 @@
path = ../vendor/SMCalloutView;
sourceTree = "<group>";
};
+ DA8848911CBB049300AB86E3 /* reachability */ = {
+ isa = PBXGroup;
+ children = (
+ DA88488D1CBB047F00AB86E3 /* reachability.h */,
+ DA88488F1CBB048E00AB86E3 /* reachability.m */,
+ );
+ name = reachability;
+ path = ..;
+ sourceTree = "<group>";
+ };
DA8933B91CCD2C6700E68420 /* Foundation Resources */ = {
isa = PBXGroup;
children = (
@@ -1848,6 +1868,8 @@
DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */,
9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */,
+ AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */,
+ AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */,
);
name = Telemetry;
sourceTree = "<group>";
@@ -1881,6 +1903,8 @@
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
+ CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
+ 1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */,
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */,
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
@@ -1968,6 +1992,7 @@
DA8847F51CBAFA5100AB86E3 /* MGLOfflineRegion.h in Headers */,
DA737EE11D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */,
DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */,
+ AC518DFF201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */,
DA88481B1CBAFA6200AB86E3 /* MGLGeometry_Private.h in Headers */,
3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
3557F7B01E1D27D300CCA5E6 /* MGLDistanceFormatter.h in Headers */,
@@ -2026,6 +2051,7 @@
96E516EF2000594F00A02306 /* NSArray+MGLAdditions.h in Headers */,
96E516F12000596800A02306 /* NSString+MGLAdditions.h in Headers */,
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */,
+ CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */,
DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */,
927FBD001F4DB05500F8BF1F /* MGLMapSnapshotter.h in Headers */,
@@ -2056,6 +2082,7 @@
96E516FB20005A4000A02306 /* MGLUserLocationHeadingBeamLayer.h in Headers */,
96E516DC2000547000A02306 /* MGLPolyline_Private.h in Headers */,
353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */,
+ AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */,
3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
DA72620C1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */,
35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
@@ -2654,6 +2681,7 @@
DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */,
3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
+ AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */,
DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */,
DA8848581CBAFB9800AB86E3 /* MGLMapboxEvents.m in Sources */,
35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
@@ -2745,6 +2773,7 @@
DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */,
3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
+ AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */,
DAA4E4271CBB730400178DFB /* MGLTilePyramidOfflineRegion.mm in Sources */,
DAA4E41C1CBB730400178DFB /* MGLAccountManager.m in Sources */,
35CE61851D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
diff --git a/platform/ios/src/MGLCameraChangeReason.h b/platform/ios/src/MGLCameraChangeReason.h
new file mode 100644
index 0000000000..6c6b3636ba
--- /dev/null
+++ b/platform/ios/src/MGLCameraChangeReason.h
@@ -0,0 +1,61 @@
+#import "MGLFoundation.h"
+
+/**
+ :nodoc:
+ Bitmask values that describe why a camera move occurred.
+
+ Values of this type are passed to the `MGLMapView`'s delegate in the following methods:
+
+ - `-mapView:shouldChangeFromCamera:toCamera:reason:`
+ - `-mapView:regionWillChangeWithReason:animated:`
+ - `-mapView:regionIsChangingWithReason:`
+ - `-mapView:regionDidChangeWithReason:animated:`
+
+ It's important to note that it's almost impossible to perform a rotate without zooming (in or out),
+ so if you'll often find `MGLCameraChangeReasonGesturePinch` set alongside `MGLCameraChangeReasonGestureRotate`.
+
+ Since there are several reasons why a zoom or rotation has occurred, it is worth considering
+ creating a combined constant, for example:
+
+ ```
+ static const MGLCameraChangeReason anyZoom = MGLCameraChangeReasonGesturePinch |
+ MGLCameraChangeReasonGestureZoomIn |
+ MGLCameraChangeReasonGestureZoomOut |
+ MGLCameraChangeReasonGestureOneFingerZoom;
+
+ static const MGLCameraChangeReason anyRotation = MGLCameraChangeReasonResetNorth | MGLCameraChangeReasonGestureRotate;
+ ```
+ */
+typedef NS_OPTIONS(NSUInteger, MGLCameraChangeReason)
+{
+ /// :nodoc: The reason for the camera change has not be specified.
+ MGLCameraChangeReasonNone = 0,
+
+ /// :nodoc: Set when a public API that moves the camera is called. This may be set for some gestures,
+ /// for example MGLCameraChangeReasonResetNorth.
+ MGLCameraChangeReasonProgrammatic = 1 << 0,
+
+ /// :nodoc: The user tapped the compass to reset the map orientation so North is up.
+ MGLCameraChangeReasonResetNorth = 1 << 1,
+
+ /// :nodoc: The user panned the map.
+ MGLCameraChangeReasonGesturePan = 1 << 2,
+
+ /// :nodoc: The user pinched to zoom in/out.
+ MGLCameraChangeReasonGesturePinch = 1 << 3,
+
+ // :nodoc: The user rotated the map.
+ MGLCameraChangeReasonGestureRotate = 1 << 4,
+
+ /// :nodoc: The user zoomed the map in (one finger double tap).
+ MGLCameraChangeReasonGestureZoomIn = 1 << 5,
+
+ /// :nodoc: The user zoomed the map out (two finger single tap).
+ MGLCameraChangeReasonGestureZoomOut = 1 << 6,
+
+ /// :nodoc: The user long pressed on the map for a quick zoom (single tap, then long press and drag up/down).
+ MGLCameraChangeReasonGestureOneFingerZoom = 1 << 7,
+
+ // :nodoc: The user panned with two fingers to tilt the map (two finger drag).
+ MGLCameraChangeReasonGestureTilt = 1 << 8
+};
diff --git a/platform/ios/src/MGLLocationManager.m b/platform/ios/src/MGLLocationManager.m
index b0d2e17d5d..85ef4ca489 100644
--- a/platform/ios/src/MGLLocationManager.m
+++ b/platform/ios/src/MGLLocationManager.m
@@ -1,9 +1,9 @@
#import "MGLLocationManager.h"
+#import "MGLTelemetryConfig.h"
#import <UIKit/UIKit.h>
static const NSTimeInterval MGLLocationManagerHibernationTimeout = 300.0;
static const NSTimeInterval MGLLocationManagerHibernationPollInterval = 5.0;
-static const CLLocationDistance MGLLocationManagerHibernationRadius = 300.0;
static const CLLocationDistance MGLLocationManagerDistanceFilter = 5.0;
static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManagerRegionIdentifier.fence.center";
@@ -122,7 +122,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage
}
- (void)establishRegionMonitoringForLocation:(CLLocation *)location {
- CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier];
+ CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier];
region.notifyOnEntry = NO;
region.notifyOnExit = YES;
[self.standardLocationManager startMonitoringForRegion:region];
@@ -151,7 +151,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage
if (location.speed > 0.0) {
[self startBackgroundTimeoutTimer];
}
- if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLLocationManagerHibernationRadius) {
+ if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius) {
[self establishRegionMonitoringForLocation:location];
}
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 31eac056e5..1dd0c4c6d3 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -210,6 +210,8 @@ public:
@property (nonatomic) UILongPressGestureRecognizer *quickZoom;
@property (nonatomic) UIPanGestureRecognizer *twoFingerDrag;
+@property (nonatomic) MGLCameraChangeReason cameraChangeReasonBitmask;
+
/// Mapping from reusable identifiers to annotation images.
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier;
@@ -506,10 +508,6 @@ public:
_doubleTap.numberOfTapsRequired = 2;
[self addGestureRecognizer:_doubleTap];
- _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
- [_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap];
- _singleTapGestureRecognizer.delegate = self;
- [self addGestureRecognizer:_singleTapGestureRecognizer];
_twoFingerDrag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDragGesture:)];
_twoFingerDrag.minimumNumberOfTouches = 2;
@@ -534,16 +532,25 @@ public:
[_quickZoom requireGestureRecognizerToFail:_doubleTap];
[self addGestureRecognizer:_quickZoom];
+ _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
+ [_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap];
+ _singleTapGestureRecognizer.delegate = self;
+ [_singleTapGestureRecognizer requireGestureRecognizerToFail:_quickZoom];
+ [self addGestureRecognizer:_singleTapGestureRecognizer];
+
// observe app activity
//
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willTerminate) name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationWillEnterForegroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationDidBecomeActiveNotification object:nil];
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
+
// set initial position
//
mbgl::CameraOptions options;
@@ -551,6 +558,9 @@ public:
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
options.padding = padding;
options.zoom = 0;
+
+ _cameraChangeReasonBitmask = MGLCameraChangeReasonNone;
+
_mbglMap->jumpTo(options);
_pendingLatitude = NAN;
_pendingLongitude = NAN;
@@ -1237,6 +1247,8 @@ public:
- (void)handleCompassTapGesture:(__unused id)sender
{
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonResetNorth;
+
[self resetNorthAnimated:YES];
if (self.userTrackingMode == MGLUserTrackingModeFollowWithHeading ||
@@ -1259,6 +1271,7 @@ public:
- (void)notifyGestureDidBegin {
BOOL animated = NO;
+
[self cameraWillChangeAnimated:animated];
_mbglMap->setGestureInProgress(true);
_changeDelimiterSuppressionDepth++;
@@ -1282,6 +1295,23 @@ public:
return _changeDelimiterSuppressionDepth > 0;
}
+- (BOOL)_shouldChangeFromCamera:(nonnull MGLMapCamera *)oldCamera toCamera:(nonnull MGLMapCamera *)newCamera
+{
+ // Check delegates first
+ if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:reason:)])
+ {
+ return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera reason:self.cameraChangeReasonBitmask];
+ }
+ else if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)])
+ {
+ return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera];
+ }
+ else
+ {
+ return YES;
+ }
+}
+
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan
{
if ( ! self.isScrollEnabled) return;
@@ -1289,7 +1319,9 @@ public:
_mbglMap->cancelTransitions();
MGLMapCamera *oldCamera = self.camera;
-
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePan;
+
if (pan.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
@@ -1303,9 +1335,8 @@ public:
CGPoint delta = [pan translationInView:pan.view];
MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:delta panGesture:pan];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->moveBy({ delta.x, delta.y });
[pan setTranslation:CGPointZero inView:pan.view];
@@ -1327,9 +1358,8 @@ public:
{
CGPoint offset = CGPointMake(velocity.x * self.decelerationRate / 4, velocity.y * self.decelerationRate / 4);
MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:offset panGesture:pan];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate));
}
@@ -1360,6 +1390,8 @@ public:
CGPoint centerPoint = [self anchorPointForGesture:pinch];
MGLMapCamera *oldCamera = self.camera;
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePinch;
+
if (pinch.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
@@ -1376,9 +1408,8 @@ public:
// Calculates the final camera zoom, has no effect within current map camera.
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
// The gesture recognizer only reports the gesture’s current center
@@ -1430,9 +1461,8 @@ public:
// Calculates the final camera zoom, this has no effect within current map camera.
double zoom = log2(newScale);
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:zoom aroundAnchorPoint:centerPoint];
-
- if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
- && ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
drift = NO;
} else {
@@ -1458,7 +1488,9 @@ public:
CGPoint centerPoint = [self anchorPointForGesture:rotate];
MGLMapCamera *oldCamera = self.camera;
-
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureRotate;
+
if (rotate.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
@@ -1485,9 +1517,8 @@ public:
}
MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
@@ -1505,9 +1536,8 @@ public:
CGFloat newDegrees = MGLDegreesFromRadians(newRadians) * -1;
MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(decelerationRate));
@@ -1552,6 +1582,7 @@ public:
}
[self deselectAnnotation:self.selectedAnnotation animated:YES];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nextElement);
+
return;
}
@@ -1562,7 +1593,7 @@ public:
CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint];
[self selectAnnotation:annotation animated:YES calloutPositioningRect:positionRect];
}
- else
+ else if (self.selectedAnnotation)
{
[self deselectAnnotation:self.selectedAnnotation animated:YES];
}
@@ -1644,6 +1675,8 @@ public:
if (doubleTap.state == UIGestureRecognizerStateEnded)
{
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomIn;
+
MGLMapCamera *oldCamera = self.camera;
double newZoom = round(self.zoomLevel) + 1.0;
@@ -1651,9 +1684,8 @@ public:
CGPoint gesturePoint = [self anchorPointForGesture:doubleTap];
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
[self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
@@ -1680,9 +1712,13 @@ public:
_mbglMap->cancelTransitions();
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomOut;
+
if (twoFingerTap.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
+
+ [self notifyGestureDidBegin];
}
else if (twoFingerTap.state == UIGestureRecognizerStateEnded)
{
@@ -1693,9 +1729,8 @@ public:
CGPoint gesturePoint = [self anchorPointForGesture:twoFingerTap];
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
_mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
@@ -1715,7 +1750,9 @@ public:
if ( ! self.isZoomEnabled) return;
_mbglMap->cancelTransitions();
-
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureOneFingerZoom;
+
if (quickZoom.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
@@ -1738,9 +1775,8 @@ public:
MGLMapCamera *oldCamera = self.camera;
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint];
-
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
@@ -1760,6 +1796,8 @@ public:
_mbglMap->cancelTransitions();
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureTilt;
+
if (twoFingerDrag.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag];
@@ -1779,8 +1817,7 @@ public:
MGLMapCamera *oldCamera = self.camera;
MGLMapCamera *toCamera = [self cameraByTiltingToPitch:pitchNew];
- if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
- [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
+ if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
_mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
@@ -2871,6 +2908,8 @@ public:
{
self.userTrackingMode = MGLUserTrackingModeNone;
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
[self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion];
}
@@ -2920,6 +2959,9 @@ public:
}
_mbglMap->cancelTransitions();
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
_mbglMap->easeTo(cameraOptions, animationOptions);
}
@@ -2943,6 +2985,8 @@ public:
if (zoomLevel == self.zoomLevel) return;
_mbglMap->cancelTransitions();
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
CGFloat duration = animated ? MGLAnimationDuration : 0;
_mbglMap->setZoom(zoomLevel,
@@ -3031,6 +3075,9 @@ public:
- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
self.userTrackingMode = MGLUserTrackingModeNone;
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
[self _setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:completion];
}
@@ -3080,6 +3127,9 @@ public:
[self willChangeValueForKey:@"visibleCoordinateBounds"];
_mbglMap->cancelTransitions();
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
_mbglMap->easeTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"visibleCoordinateBounds"];
}
@@ -3113,6 +3163,8 @@ public:
CGFloat duration = animated ? MGLAnimationDuration : 0;
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
if (self.userTrackingMode == MGLUserTrackingModeNone)
{
_mbglMap->setBearing(direction,
@@ -3197,6 +3249,9 @@ public:
[self willChangeValueForKey:@"camera"];
_mbglMap->cancelTransitions();
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding];
_mbglMap->easeTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
@@ -3253,6 +3308,9 @@ public:
[self willChangeValueForKey:@"camera"];
_mbglMap->cancelTransitions();
+
+ self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
+
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets];
_mbglMap->flyTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
@@ -3413,6 +3471,13 @@ public:
return [self metersPerPointAtLatitude:latitude];
}
+#pragma mark - Camera Change Reason -
+
+- (void)resetCameraChangeReason
+{
+ self.cameraChangeReasonBitmask = MGLCameraChangeReasonNone;
+}
+
#pragma mark - Styling -
- (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs
@@ -5359,9 +5424,16 @@ public:
}
}
- if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
+ if ( ! [self isSuppressingChangeDelimiters] )
{
- [self.delegate mapView:self regionWillChangeAnimated:animated];
+ if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeWithReason:animated:)])
+ {
+ [self.delegate mapView:self regionWillChangeWithReason:self.cameraChangeReasonBitmask animated:animated];
+ }
+ else if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
+ {
+ [self.delegate mapView:self regionWillChangeAnimated:animated];
+ }
}
}
@@ -5375,8 +5447,12 @@ public:
if (!self.scaleBar.hidden) {
[(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]];
}
-
- if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
+
+ if ([self.delegate respondsToSelector:@selector(mapView:regionIsChangingWithReason:)])
+ {
+ [self.delegate mapView:self regionIsChangingWithReason:self.cameraChangeReasonBitmask];
+ }
+ else if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
{
[self.delegate mapViewRegionIsChanging:self];
}
@@ -5389,9 +5465,13 @@ public:
[self updateCompass];
- if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
+ if ( ! [self isSuppressingChangeDelimiters])
{
- if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
+ BOOL respondsToSelector = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)];
+ BOOL respondsToSelectorWithReason = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeWithReason:animated:)];
+
+ if ((respondsToSelector || respondsToSelectorWithReason) &&
+ ([UIApplication sharedApplication].applicationState == UIApplicationStateActive))
{
_featureAccessibilityElements = nil;
_visiblePlaceFeatures = nil;
@@ -5403,7 +5483,17 @@ public:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
}
- [self.delegate mapView:self regionDidChangeAnimated:animated];
+
+ if (respondsToSelectorWithReason)
+ {
+ [self.delegate mapView:self regionDidChangeWithReason:self.cameraChangeReasonBitmask animated:animated];
+ }
+ else if (respondsToSelector)
+ {
+ [self.delegate mapView:self regionDidChangeAnimated:animated];
+ }
+
+ [self resetCameraChangeReason];
}
}
diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h
index 096711fcbb..0368d8413c 100644
--- a/platform/ios/src/MGLMapViewDelegate.h
+++ b/platform/ios/src/MGLMapViewDelegate.h
@@ -1,6 +1,7 @@
#import <UIKit/UIKit.h>
#import "MGLTypes.h"
+#import "MGLCameraChangeReason.h"
NS_ASSUME_NONNULL_BEGIN
@@ -22,17 +23,80 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark Responding to Map Position Changes
/**
+ Asks the delegate whether the map view should be allowed to change from the
+ existing camera to the new camera in response to a user gesture.
+
+ This method is called as soon as the user gesture is recognized. It is not
+ called in response to a programmatic camera change, such as by setting the
+ `centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
+
+ This method is called many times during gesturing, so you should avoid performing
+ complex or performance-intensive tasks in your implementation.
+
+ @param mapView The map view that the user is manipulating.
+ @param oldCamera The camera representing the viewpoint at the moment the
+ gesture is recognized. If this method returns `NO`, the map view’s camera
+ continues to be this camera.
+ @param newCamera The expected camera after the gesture completes. If this
+ method returns `YES`, this camera becomes the map view’s camera.
+ @return A Boolean value indicating whether the map view should stay at
+ `oldCamera` or change to `newCamera`.
+ */
+- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
+
+/**
+ :nodoc:
+ Asks the delegate whether the map view should be allowed to change from the
+ existing camera to the new camera in response to a user gesture.
+
+ This method is called as soon as the user gesture is recognized. It is not
+ called in response to a programmatic camera change, such as by setting the
+ `centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
+
+ This method is called many times during gesturing, so you should avoid performing
+ complex or performance-intensive tasks in your implementation.
+
+ @param mapView The map view that the user is manipulating.
+ @param oldCamera The camera representing the viewpoint at the moment the
+ gesture is recognized. If this method returns `NO`, the map view’s camera
+ continues to be this camera.
+ @param newCamera The expected camera after the gesture completes. If this
+ method returns `YES`, this camera becomes the map view’s camera.
+ @param reason The reason for the camera change.
+ @return A Boolean value indicating whether the map view should stay at
+ `oldCamera` or change to `newCamera`.
+
+ @note If this method is implemented `-mapView:shouldChangeFromCamera:toCamera:` will not be called.
+ */
+- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera reason:(MGLCameraChangeReason)reason;
+
+/**
Tells the delegate that the viewpoint depicted by the map view is about to change.
This method is called whenever the currently displayed map camera will start
changing for any reason.
-
+
@param mapView The map view whose viewpoint will change.
@param animated Whether the change will cause an animated effect on the map.
*/
- (void)mapView:(MGLMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
/**
+ :nodoc:
+ Tells the delegate that the viewpoint depicted by the map view is about to change.
+
+ This method is called whenever the currently displayed map camera will start
+ changing for any reason.
+
+ @param mapView The map view whose viewpoint will change.
+ @param animated Whether the change will cause an animated effect on the map.
+ @param reason The reason for the camera change.
+
+ @note If this method is implemented `-mapView:regionWillChangeAnimated:` will not be called.
+ */
+- (void)mapView:(MGLMapView *)mapView regionWillChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated;
+
+/**
Tells the delegate that the viewpoint depicted by the map view is changing.
This method is called as the currently displayed map camera changes as part of
@@ -49,6 +113,26 @@ NS_ASSUME_NONNULL_BEGIN
- (void)mapViewRegionIsChanging:(MGLMapView *)mapView;
/**
+ :nodoc:
+ Tells the delegate that the viewpoint depicted by the map view is changing.
+
+ This method is called as the currently displayed map camera changes as part of
+ an animation, whether due to a user gesture or due to a call to a method such
+ as `-[MGLMapView setCamera:animated:]`. This method can be called before
+ `-mapViewDidFinishLoadingMap:` is called.
+
+ During the animation, this method may be called many times to report updates to
+ the viewpoint. Therefore, your implementation of this method should be as lightweight
+ as possible to avoid affecting performance.
+
+ @param mapView The map view whose viewpoint is changing.
+ @param reason The reason for the camera change.
+
+ @note If this method is implemented `-mapViewRegionIsChanging:` will not be called.
+ */
+- (void)mapView:(MGLMapView *)mapView regionIsChangingWithReason:(MGLCameraChangeReason)reason;
+
+/**
Tells the delegate that the viewpoint depicted by the map view has finished
changing.
@@ -62,26 +146,21 @@ NS_ASSUME_NONNULL_BEGIN
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
/**
- Asks the delegate whether the map view should be allowed to change from the
- existing camera to the new camera in response to a user gesture.
-
- This method is called as soon as the user gesture is recognized. It is not
- called in response to a programmatic camera change, such as by setting the
- `centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
-
- This method is called many times during gesturing, so you should avoid performing
- complex or performance-intensive tasks in your implementation.
-
- @param mapView The map view that the user is manipulating.
- @param oldCamera The camera representing the viewpoint at the moment the
- gesture is recognized. If this method returns `NO`, the map view’s camera
- continues to be this camera.
- @param newCamera The expected camera after the gesture completes. If this
- method returns `YES`, this camera becomes the map view’s camera.
- @return A Boolean value indicating whether the map view should stay at
- `oldCamera` or change to `newCamera`.
+ :nodoc:
+ Tells the delegate that the viewpoint depicted by the map view has finished
+ changing.
+
+ This method is called whenever the currently displayed map camera has finished
+ changing, after any calls to `-mapViewRegionIsChanging:` due to animation. Therefore,
+ this method can be called before `-mapViewDidFinishLoadingMap:` is called.
+
+ @param mapView The map view whose viewpoint has changed.
+ @param animated Whether the change caused an animated effect on the map.
+ @param reason The reason for the camera change.
+
+ @note If this method is implemented `-mapView:regionDidChangeAnimated:` will not be called.
*/
-- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
+- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated;
#pragma mark Loading the Map
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index d59972f5bf..273af5b3bc 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -6,6 +6,7 @@
#import "NSException+MGLAdditions.h"
#import "MGLAPIClient.h"
#import "MGLLocationManager.h"
+#import "MGLTelemetryConfig.h"
#include <mbgl/storage/reachability.h>
#include <sys/sysctl.h>
@@ -172,6 +173,8 @@ const NSTimeInterval MGLFlushInterval = 180;
- (instancetype) init {
self = [super init];
if (self) {
+ [MGLTelemetryConfig.sharedConfig configurationFromKey:[[NSUserDefaults standardUserDefaults] objectForKey:MGLMapboxMetricsProfile]];
+
_currentAccountTypeValue = @0;
_currentMetricsEnabledValue = YES;
diff --git a/platform/ios/src/MGLTelemetryConfig.h b/platform/ios/src/MGLTelemetryConfig.h
new file mode 100644
index 0000000000..527d344291
--- /dev/null
+++ b/platform/ios/src/MGLTelemetryConfig.h
@@ -0,0 +1,18 @@
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MGLTelemetryConfig : NSObject
+
+@property (nonatomic) CLLocationDistance MGLLocationManagerHibernationRadius;
+
+extern NSString *const MGLMapboxMetricsProfile;
+
++ (nullable instancetype)sharedConfig;
+
+- (void)configurationFromKey:(NSString *)key;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/ios/src/MGLTelemetryConfig.m b/platform/ios/src/MGLTelemetryConfig.m
new file mode 100644
index 0000000000..828bafb14f
--- /dev/null
+++ b/platform/ios/src/MGLTelemetryConfig.m
@@ -0,0 +1,35 @@
+#import "MGLTelemetryConfig.h"
+
+static const CLLocationDistance MGLConfigHibernationRadiusDefault = 300.0;
+static const CLLocationDistance MGLConfigHibernationRadiusWide = 600.0;
+
+NSString *const MGLMapboxMetricsProfile = @"MGLMapboxMetricsProfile";
+
+static NSString *const MGLConfigHibernationRadiusWideKey = @"WideGeoFence";
+
+@implementation MGLTelemetryConfig
+
+- (instancetype) init {
+ self = [super init];
+ if (self) {
+ _MGLLocationManagerHibernationRadius = MGLConfigHibernationRadiusDefault;
+ }
+ return self;
+}
+
++ (nullable instancetype)sharedConfig {
+ static dispatch_once_t onceToken;
+ static MGLTelemetryConfig *_sharedConfig;
+ dispatch_once(&onceToken, ^{
+ _sharedConfig = [[self alloc] init];
+ });
+ return _sharedConfig;
+}
+
+- (void)configurationFromKey:(NSString *)key {
+ if ([key isEqualToString:MGLConfigHibernationRadiusWideKey]) {
+ _MGLLocationManagerHibernationRadius = MGLConfigHibernationRadiusWide;
+ }
+}
+
+@end
diff --git a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
index 50f101e86b..4d11b000b9 100644
--- a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
+++ b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
@@ -13,6 +13,10 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
func mapViewRegionIsChanging(_ mapView: MGLMapView) {}
+ func mapViewRegionIsChanging(_ mapView: MGLMapView, reason: MGLCameraChangeReason) {}
+
+ func mapView(_ mapView: MGLMapView, regionIsChangingWith reason: MGLCameraChangeReason) {}
+
func mapView(_ mapView: MGLMapView, didChange mode: MGLUserTrackingMode, animated: Bool) {}
func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {}
@@ -33,10 +37,16 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
func mapView(_ mapView: MGLMapView, didDeselect annotation: MGLAnnotation) {}
+ func mapView(_ mapView: MGLMapView, didSingleTapAt coordinate: CLLocationCoordinate2D) {}
+
func mapView(_ mapView: MGLMapView, regionDidChangeAnimated animated: Bool) {}
+ func mapView(_ mapView: MGLMapView, regionDidChangeWith reason: MGLCameraChangeReason, animated: Bool) {}
+
func mapView(_ mapView: MGLMapView, regionWillChangeAnimated animated: Bool) {}
+ func mapView(_ mapView: MGLMapView, regionWillChangeWith reason: MGLCameraChangeReason, animated: Bool) {}
+
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {}
func mapView(_ mapView: MGLMapView, didUpdate userLocation: MGLUserLocation?) {}
@@ -79,4 +89,5 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera) -> Bool { return false }
+ func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool { return false }
}
diff --git a/platform/ios/uitest/MapViewTests.m b/platform/ios/uitest/MapViewTests.m
index 4ed3d89399..ba15af918a 100644
--- a/platform/ios/uitest/MapViewTests.m
+++ b/platform/ios/uitest/MapViewTests.m
@@ -538,10 +538,13 @@
userInfo:@{ @"animated" : @(animated) }];
}
-- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
+- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated {
+
[[NSNotificationCenter defaultCenter] postNotificationName:@"regionDidChangeAnimated"
object:mapView
- userInfo:@{ @"animated" : @(animated) }];
+ userInfo:@{ @"animated" : @(animated),
+ @"reason" : @(reason)
+ }];
}
- (void)testDelegatesStartStopLocatingUser {
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 440d4d9787..0c8c59700d 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -22,6 +22,11 @@
* Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585))
+## v0.6.2
+
+* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
+* Fixed an issue that caused `-[MGLMapSnapshotter pointForCoordinate:]` to return the wrong point. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
+
## v0.6.1 - January 16, 2018
This version of the Mapbox macOS SDK corresponds to version 3.7.3 of the Mapbox Maps SDK for iOS.