Merge branch 'release-ios-v3.1.0'
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@@ -49,14 +49,26 @@ Known issues:
|
||||
- Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
|
||||
- Resolved in 2.2.0
|
||||
|
||||
## iOS master
|
||||
## iOS 3.1.2
|
||||
|
||||
- You can once again install the static framework without manually linking several framework and library dependencies. ([#4029](https://github.com/mapbox/mapbox-gl-native/pull/4029))
|
||||
- The location manager used by MGLMapView to show the user’s location is now paused when the application is sent to the background. ([#4034](https://github.com/mapbox/mapbox-gl-native/pull/4034))
|
||||
|
||||
## iOS 3.1.1
|
||||
|
||||
- Corrected the dynamic framework’s minimum deployment target to iOS 8.0. ([#3872](https://github.com/mapbox/mapbox-gl-native/pull/3872))
|
||||
- Fixed Fabric compatibility. ([#3847](https://github.com/mapbox/mapbox-gl-native/pull/3847))
|
||||
- Fixed a crash that can occur when reselecting an annotation. ([#3881](https://github.com/mapbox/mapbox-gl-native/pull/3881))
|
||||
- Fixed an issue preventing the Latitude inspectable from working when it is set before setting the Zoom Level inspectable in Interface Builder. ([#3886](https://github.com/mapbox/mapbox-gl-native/pull/3886))
|
||||
- Fixed an issue that incorrectly expanded the tappable area of an annotation and prevented the annotation’s alignment rect insets from having any effect on the tappable area. ([#3898](https://github.com/mapbox/mapbox-gl-native/pull/3898))
|
||||
- Fixed an issue preventing `-[MGLMapViewDelegate mapView:tapOnCalloutForAnnotation:]` from being called when a non-custom callout view is tapped. ([#3875](https://github.com/mapbox/mapbox-gl-native/pull/3875))
|
||||
|
||||
- Polygons and polylines now default to using the map view's tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028))
|
||||
- The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068))
|
||||
|
||||
## iOS 3.1.0
|
||||
|
||||
- The SDK is now distributed as a dynamic framework instead of a static library, resulting in a simpler installation workflow and significantly reduced download size. The framework contains both simulator and device content; due to [an Xcode bug](http://www.openradar.me/radar?id=6409498411401216), you’ll need to strip out the simulator content before submitting your application to the App Store. ([#3183](https://github.com/mapbox/mapbox-gl-native/pull/3183))
|
||||
- The SDK is now distributed as a dynamic framework instead of a static library, resulting in a simpler installation workflow and significantly reduced download size. The framework contains both simulator and device content. If you install the dynamic framework manually, you’ll need to strip out the simulator content before submitting your application to the App Store due to [an Xcode bug](http://www.openradar.me/radar?id=6409498411401216); see the installation instructions included with the framework for details. ([#3183](https://github.com/mapbox/mapbox-gl-native/pull/3183))
|
||||
- Fixed an issue causing the entire MGLMapView to leak. ([#3447](https://github.com/mapbox/mapbox-gl-native/pull/3447))
|
||||
- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090))
|
||||
- You can now modify an annotation’s image after adding the annotation to the map. ([#3146](https://github.com/mapbox/mapbox-gl-native/pull/3146))
|
||||
|
||||
@@ -138,6 +138,10 @@ public:
|
||||
// North Orientation
|
||||
void setNorthOrientation(NorthOrientation);
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
|
||||
// Constrain mode
|
||||
void setConstrainMode(ConstrainMode);
|
||||
ConstrainMode getConstrainMode() const;
|
||||
|
||||
// Size
|
||||
uint16_t getWidth() const;
|
||||
|
||||
@@ -24,6 +24,7 @@ enum class GLContextMode : EnumType {
|
||||
// We can choose to constrain the map both horizontally or vertically, or only
|
||||
// vertically e.g. while panning.
|
||||
enum class ConstrainMode : EnumType {
|
||||
None,
|
||||
HeightOnly,
|
||||
WidthAndHeight,
|
||||
};
|
||||
|
||||
3
ios/framework/Mapbox-static.h
Normal file
3
ios/framework/Mapbox-static.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
@@ -79,7 +79,7 @@ This is the recommended workflow for manually integrating the SDK into an applic
|
||||
|
||||
1. Build from source manually per above.
|
||||
|
||||
1. Open the project editor and select your application target. Drag `build/ios/pkg/dynamic/Mapbox.framework` into the “Embedded Binaries” section of the General tab. In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish.
|
||||
1. Open the project editor and select your application target. Drag `build/ios/pkg/dynamic/Mapbox.framework` into the “Embedded Binaries” section of the General tab. (Don’t drag it into the “Linked Frameworks and Libraries” section; Xcode will add it there automatically.) In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish.
|
||||
|
||||
1. In the Build Phases tab, click the + button at the top and select “New Run Script Phase”. Enter the following code into the script text field:
|
||||
|
||||
@@ -95,7 +95,7 @@ If your application targets iOS 7.x, you’ll need to install the static framewo
|
||||
|
||||
1. Build from source manually per above.
|
||||
|
||||
1. Open the project editor and select your application target. Drag `build/ios/pkg/static/Mapbox.framework` into the “Embedded Binaries” section of the General tab. In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish.
|
||||
1. Open the project editor and select your application target. Drag `build/ios/pkg/static/Mapbox.framework` into the “Embedded Binaries” section of the General tab. (Don’t drag it into the “Linked Frameworks and Libraries” section; Xcode will add it there automatically.) In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish.
|
||||
|
||||
1. Add the following Cocoa Touch frameworks and libraries to the “Linked Frameworks and Libraries” section:
|
||||
|
||||
@@ -104,9 +104,9 @@ If your application targets iOS 7.x, you’ll need to install the static framewo
|
||||
- `MobileCoreServices.framework`
|
||||
- `QuartzCore.framework`
|
||||
- `SystemConfiguration.framework`
|
||||
- `libc++.dylib`
|
||||
- `libsqlite3.dylib`
|
||||
- `libz.dylib`
|
||||
- `libc++.tbd`
|
||||
- `libsqlite3.tbd`
|
||||
- `libz.tbd`
|
||||
|
||||
1. In the Build Settings tab, add `-ObjC` to the “Other Linker Flags” (`OTHER_LDFLAGS`) build setting.
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
Pod::Spec.new do |m|
|
||||
|
||||
m.name = 'Mapbox-iOS-SDK'
|
||||
m.version = '3.1.0-pre.3-symbols'
|
||||
m.version = '3.1.2'
|
||||
|
||||
m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
|
||||
m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.'
|
||||
m.homepage = 'https://www.mapbox.com/ios-sdk/'
|
||||
m.license = { :type => 'BSD', :file => 'LICENSE.md' }
|
||||
m.author = { 'Mapbox' => 'mobile@mapbox.com' }
|
||||
m.screenshot = 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/ios/screenshot.png'
|
||||
m.screenshot = 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/platform/ios/screenshot.png'
|
||||
m.social_media_url = 'https://twitter.com/mapbox'
|
||||
m.documentation_url = 'https://www.mapbox.com/ios-sdk/'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The Mapbox iOS SDK is an open-source framework for embedding interactive map views with scalable, customizable vector maps into Cocoa Touch applications on iOS 7.0 and above using Objective-C, Swift, or Interface Builder. It takes stylesheets that conform to the [Mapbox GL Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/), applies them to vector tiles that conform to the [Mapbox Vector Tile Specification](https://www.mapbox.com/developers/vector-tiles/), and renders them using OpenGL.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
|
||||
For setup information, check out the [Mapbox iOS SDK homepage](https://www.mapbox.com/ios-sdk/). For detailed usage instructions, read “[First steps with the Mapbox iOS SDK](https://www.mapbox.com/help/first-steps-ios-sdk/)” and consult the [online examples](https://www.mapbox.com/ios-sdk/examples/). A [full changelog](https://github.com/mapbox/mapbox-gl-native/blob/master/CHANGELOG.md) is also available.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ The Mapbox iOS SDK is an open-source framework for embedding interactive map vie
|
||||
|
||||
For more information, check out the [Mapbox iOS SDK homepage](https://www.mapbox.com/ios-sdk/) and the [full changelog](https://github.com/mapbox/mapbox-gl-native/blob/master/CHANGELOG.md) online.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -42,9 +42,9 @@ If your application targets iOS 7.x, you’ll need to install the static framewo
|
||||
- `MobileCoreServices.framework`
|
||||
- `QuartzCore.framework`
|
||||
- `SystemConfiguration.framework`
|
||||
- `libc++.dylib`
|
||||
- `libsqlite3.dylib`
|
||||
- `libz.dylib`
|
||||
- `libc++.tbd`
|
||||
- `libsqlite3.tbd`
|
||||
- `libz.tbd`
|
||||
|
||||
1. In the Build Settings tab, add `-ObjC` to the “Other Linker Flags” (`OTHER_LDFLAGS`) build setting.
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
'DEFINES_MODULE': 'YES',
|
||||
'DYLIB_INSTALL_NAME_BASE': '@rpath',
|
||||
'INFOPLIST_FILE': '../platform/ios/framework/Info.plist',
|
||||
'IPHONEOS_DEPLOYMENT_TARGET': '8.0',
|
||||
'LD_RUNPATH_SEARCH_PATHS': [
|
||||
'$(inherited)',
|
||||
'@executable_path/Frameworks',
|
||||
|
||||
@@ -188,10 +188,13 @@ if [[ ${BUILD_STATIC} == true ]]; then
|
||||
step "Copying static library headers…"
|
||||
mkdir -p "${OUTPUT}/static/${NAME}.framework/Headers"
|
||||
cp -pv platform/{darwin,ios}/include/*.h "${OUTPUT}/static/${NAME}.framework/Headers"
|
||||
cat platform/ios/framework/Mapbox-static.h > "${OUTPUT}/static/${NAME}.framework/Headers/Mapbox.h"
|
||||
cat platform/ios/framework/Mapbox.h >> "${OUTPUT}/static/${NAME}.framework/Headers/Mapbox.h"
|
||||
fi
|
||||
|
||||
step "Copying library resources…"
|
||||
SHORT_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' )
|
||||
SEM_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' )
|
||||
SHORT_VERSION=${SEM_VERSION%-*}
|
||||
cp -pv LICENSE.md "${OUTPUT}"
|
||||
cp -rv platform/ios/app/Settings.bundle "${OUTPUT}"
|
||||
if [[ ${BUILD_STATIC} == true ]]; then
|
||||
@@ -202,11 +205,16 @@ if [[ ${BUILD_STATIC} == true ]]; then
|
||||
plutil -replace CFBundleName -string ${NAME} "${OUTPUT}/static/${NAME}.framework/Info.plist"
|
||||
plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${OUTPUT}/static/${NAME}.framework/Info.plist"
|
||||
plutil -replace CFBundleVersion -string ${PROJ_VERSION} "${OUTPUT}/static/${NAME}.framework/Info.plist"
|
||||
plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${OUTPUT}/static/${NAME}.framework/Info.plist"
|
||||
plutil -replace MGLCommitHash -string "${HASH}" "${OUTPUT}/static/${NAME}.framework/Info.plist"
|
||||
mkdir "${OUTPUT}/static/${NAME}.framework/Modules"
|
||||
cp -pv platform/ios/framework/modulemap "${OUTPUT}/static/${NAME}.framework/Modules/module.modulemap"
|
||||
fi
|
||||
if [[ ${BUILD_DYNAMIC} == true ]]; then
|
||||
plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist"
|
||||
plutil -replace CFBundleVersion -string "${PROJ_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist"
|
||||
plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist"
|
||||
plutil -replace MGLCommitHash -string "${HASH}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist"
|
||||
cp -pv platform/ios/framework/strip-frameworks.sh "${OUTPUT}/dynamic/${NAME}.framework/strip-frameworks.sh"
|
||||
fi
|
||||
sed -n -e '/^## iOS/,$p' CHANGELOG.md > "${OUTPUT}/CHANGELOG.md"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#import "MGLAccountManager_Private.h"
|
||||
#import "MGLMapboxEvents.h"
|
||||
#import "MGLMapView.h"
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
#import "NSProcessInfo+MGLAdditions.h"
|
||||
#import "NSString+MGLAdditions.h"
|
||||
|
||||
#import "FABKitProtocol.h"
|
||||
#import "Fabric+FABKits.h"
|
||||
@@ -93,6 +95,14 @@
|
||||
} else {
|
||||
NSLog(@"MGLAccountManager is used in a project that doesn't have Fabric.");
|
||||
}
|
||||
|
||||
// https://github.com/mapbox/mapbox-gl-native/issues/2966
|
||||
mgl_linkBundleCategory();
|
||||
mgl_linkStringCategory();
|
||||
mgl_linkProcessInfoCategory();
|
||||
|
||||
// https://github.com/mapbox/mapbox-gl-native/issues/3113
|
||||
[MGLMapView class];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -147,6 +147,7 @@ public:
|
||||
GLKViewDelegate,
|
||||
CLLocationManagerDelegate,
|
||||
UIActionSheetDelegate,
|
||||
SMCalloutViewDelegate,
|
||||
MGLCalloutViewDelegate,
|
||||
UIAlertViewDelegate,
|
||||
MGLMultiPointDelegate,
|
||||
@@ -313,7 +314,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
_mbglFileSource = new mbgl::DefaultFileSource([fileCachePath UTF8String], [[[[NSBundle mainBundle] resourceURL] path] UTF8String]);
|
||||
|
||||
// setup mbgl map
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);
|
||||
|
||||
// start paused if in IB
|
||||
if (_isTargetingInterfaceBuilder || background) {
|
||||
@@ -759,7 +760,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
// This is the delegate of the GLKView object's display call.
|
||||
- (void)glkView:(__unused GLKView *)view drawInRect:(__unused CGRect)rect
|
||||
{
|
||||
if ( ! self.isDormant)
|
||||
if ( ! self.dormant)
|
||||
{
|
||||
CGFloat zoomFactor = _mbglMap->getMaxZoom() - _mbglMap->getMinZoom() + 1;
|
||||
CGFloat cpuFactor = (CGFloat)[[NSProcessInfo processInfo] processorCount];
|
||||
@@ -905,7 +906,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
{
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
if ( ! self.isDormant)
|
||||
if ( ! self.dormant)
|
||||
{
|
||||
[self validateDisplayLink];
|
||||
self.dormant = YES;
|
||||
@@ -919,6 +920,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
BOOL isVisible = self.superview && self.window;
|
||||
if (isVisible && ! _displayLink)
|
||||
{
|
||||
if (_mbglMap->getConstrainMode() == mbgl::ConstrainMode::None)
|
||||
{
|
||||
_mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
|
||||
}
|
||||
|
||||
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateFromDisplayLink)];
|
||||
_displayLink.frameInterval = MGLTargetFrameInterval;
|
||||
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
||||
@@ -951,6 +957,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
{
|
||||
self.dormant = YES;
|
||||
|
||||
[self validateLocationServices];
|
||||
|
||||
[MGLMapboxEvents flush];
|
||||
|
||||
_displayLink.paused = YES;
|
||||
@@ -1000,6 +1008,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
_mbglMap->resume();
|
||||
|
||||
_displayLink.paused = NO;
|
||||
|
||||
[self validateLocationServices];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1482,6 +1492,14 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
return [self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)];
|
||||
}
|
||||
|
||||
- (void)calloutViewClicked:(__unused SMCalloutView *)calloutView
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)])
|
||||
{
|
||||
[self.delegate mapView:self tapOnCalloutForAnnotation:self.selectedAnnotation];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)calloutViewTapped:(__unused MGLCompactCalloutView *)calloutView
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)])
|
||||
@@ -2643,7 +2661,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
|
||||
// Filter out any annotation whose image is unselectable or for which
|
||||
// hit testing fails.
|
||||
std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag)
|
||||
auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(),
|
||||
[&](const MGLAnnotationTag annotationTag)
|
||||
{
|
||||
id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag];
|
||||
NSAssert(annotation, @"Unknown annotation found nearby tap");
|
||||
@@ -2660,6 +2679,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
centeredAtCoordinate:annotation.coordinate];
|
||||
return !!!CGRectIntersectsRect(annotationRect, hitRect);
|
||||
});
|
||||
nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end));
|
||||
}
|
||||
|
||||
MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound;
|
||||
@@ -2689,19 +2709,28 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
if (_selectedAnnotationTag == MGLAnnotationTagNotFound
|
||||
|| _selectedAnnotationTag == _annotationsNearbyLastTap.back())
|
||||
{
|
||||
// Either an annotation from this set hasn’t been selected
|
||||
// before or the last annotation in the set was selected. Wrap
|
||||
// around to the first annotation in the set.
|
||||
// Either no annotation is selected or the last annotation in
|
||||
// the set was selected. Wrap around to the first annotation in
|
||||
// the set.
|
||||
hitAnnotationTag = _annotationsNearbyLastTap.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step to the next annotation in the set.
|
||||
auto result = std::find(_annotationsNearbyLastTap.begin(),
|
||||
_annotationsNearbyLastTap.end(),
|
||||
_selectedAnnotationTag);
|
||||
auto distance = std::distance(_annotationsNearbyLastTap.begin(), result);
|
||||
hitAnnotationTag = _annotationsNearbyLastTap[distance + 1];
|
||||
if (result == _annotationsNearbyLastTap.end())
|
||||
{
|
||||
// An annotation from this set hasn’t been selected before.
|
||||
// Select the first (nearest) one.
|
||||
hitAnnotationTag = _annotationsNearbyLastTap.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step to the next annotation in the set.
|
||||
auto distance = std::distance(_annotationsNearbyLastTap.begin(), result);
|
||||
hitAnnotationTag = _annotationsNearbyLastTap[distance + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2997,6 +3026,48 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
|
||||
#pragma mark - User Location -
|
||||
|
||||
- (void)validateLocationServices
|
||||
{
|
||||
BOOL shouldEnableLocationServices = self.showsUserLocation && !self.dormant;
|
||||
|
||||
if (shouldEnableLocationServices && ! self.locationManager)
|
||||
{
|
||||
self.locationManager = [[CLLocationManager alloc] init];
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
|
||||
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)
|
||||
{
|
||||
BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"];
|
||||
if (!hasLocationDescription)
|
||||
{
|
||||
[NSException raise:@"Missing Location Services usage description" format:
|
||||
@"In iOS 8 and above, this app must have a value for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist."];
|
||||
}
|
||||
|
||||
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"])
|
||||
{
|
||||
[self.locationManager requestAlwaysAuthorization];
|
||||
}
|
||||
else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"])
|
||||
{
|
||||
[self.locationManager requestWhenInUseAuthorization];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
self.locationManager.headingFilter = 5.0;
|
||||
self.locationManager.delegate = self;
|
||||
[self.locationManager startUpdatingLocation];
|
||||
}
|
||||
else if ( ! shouldEnableLocationServices && self.locationManager)
|
||||
{
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
[self.locationManager stopUpdatingHeading];
|
||||
self.locationManager.delegate = nil;
|
||||
self.locationManager = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setShowsUserLocation:(BOOL)showsUserLocation
|
||||
{
|
||||
if (showsUserLocation == _showsUserLocation || _isTargetingInterfaceBuilder) return;
|
||||
@@ -3014,42 +3085,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
|
||||
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
|
||||
|
||||
self.locationManager = [CLLocationManager new];
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
|
||||
// enable iOS 8+ location authorization API
|
||||
//
|
||||
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)])
|
||||
{
|
||||
BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] ||
|
||||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"];
|
||||
if (!hasLocationDescription)
|
||||
{
|
||||
[NSException raise:@"Missing Location Services usage description" format:
|
||||
@"In iOS 8 and above, this app must have a value for NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in its Info.plist."];
|
||||
}
|
||||
// request location permissions, if both keys exist ask for less permissive
|
||||
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"])
|
||||
{
|
||||
[self.locationManager requestWhenInUseAuthorization];
|
||||
}
|
||||
else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"])
|
||||
{
|
||||
[self.locationManager requestAlwaysAuthorization];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
self.locationManager.headingFilter = 5.0;
|
||||
self.locationManager.delegate = self;
|
||||
[self.locationManager startUpdatingLocation];
|
||||
[self validateLocationServices];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
[self.locationManager stopUpdatingHeading];
|
||||
self.locationManager.delegate = nil;
|
||||
self.locationManager = nil;
|
||||
[self validateLocationServices];
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)])
|
||||
{
|
||||
|
||||
@@ -249,7 +249,7 @@ public:
|
||||
NSString *cachePath = cacheURL ? cacheURL.path : @"";
|
||||
_mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [[[[NSBundle mainBundle] resourceURL] path] UTF8String]);
|
||||
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);
|
||||
|
||||
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
|
||||
// we can’t display a map, so don’t even bother to have a map layer.
|
||||
@@ -559,19 +559,24 @@ public:
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow {
|
||||
if (self.dormant && self.window) {
|
||||
NSWindow *window = self.window;
|
||||
if (self.dormant && window) {
|
||||
_mbglMap->resume();
|
||||
self.dormant = NO;
|
||||
}
|
||||
|
||||
[self.window addObserver:self
|
||||
forKeyPath:@"contentLayoutRect"
|
||||
options:NSKeyValueObservingOptionInitial
|
||||
context:NULL];
|
||||
[self.window addObserver:self
|
||||
forKeyPath:@"titlebarAppearsTransparent"
|
||||
options:NSKeyValueObservingOptionInitial
|
||||
context:NULL];
|
||||
if (window && _mbglMap->getConstrainMode() == mbgl::ConstrainMode::None) {
|
||||
_mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
|
||||
}
|
||||
|
||||
[window addObserver:self
|
||||
forKeyPath:@"contentLayoutRect"
|
||||
options:NSKeyValueObservingOptionInitial
|
||||
context:NULL];
|
||||
[window addObserver:self
|
||||
forKeyPath:@"titlebarAppearsTransparent"
|
||||
options:NSKeyValueObservingOptionInitial
|
||||
context:NULL];
|
||||
}
|
||||
|
||||
- (BOOL)wantsLayer {
|
||||
@@ -1712,7 +1717,7 @@ public:
|
||||
|
||||
// Filter out any annotation whose image is unselectable or for which
|
||||
// hit testing fails.
|
||||
std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) {
|
||||
auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) {
|
||||
NSAssert(_annotationContextsByAnnotationTag.count(annotationTag) != 0, @"Unknown annotation found nearby click");
|
||||
id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag];
|
||||
if (!annotation) {
|
||||
@@ -1731,6 +1736,7 @@ public:
|
||||
return !!![annotationImage.image hitTestRect:hitRect withImageDestinationRect:annotationRect
|
||||
context:nil hints:nil flipped:NO];
|
||||
});
|
||||
nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end));
|
||||
}
|
||||
|
||||
MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound;
|
||||
@@ -1757,17 +1763,23 @@ public:
|
||||
// set of annotations as we do now. Cycle through them.
|
||||
if (_lastSelectedAnnotationTag == MGLAnnotationTagNotFound
|
||||
|| _lastSelectedAnnotationTag == _annotationsNearbyLastClick.back()) {
|
||||
// Either an annotation from this set hasn’t been selected
|
||||
// before or the last annotation in the set was selected. Wrap
|
||||
// around to the first annotation in the set.
|
||||
// Either no annotation is selected or the last annotation in
|
||||
// the set was selected. Wrap around to the first annotation in
|
||||
// the set.
|
||||
hitAnnotationTag = _annotationsNearbyLastClick.front();
|
||||
} else {
|
||||
// Step to the next annotation in the set.
|
||||
auto result = std::find(_annotationsNearbyLastClick.begin(),
|
||||
_annotationsNearbyLastClick.end(),
|
||||
_lastSelectedAnnotationTag);
|
||||
auto distance = std::distance(_annotationsNearbyLastClick.begin(), result);
|
||||
hitAnnotationTag = _annotationsNearbyLastClick[distance + 1];
|
||||
if (result == _annotationsNearbyLastClick.end()) {
|
||||
// An annotation from this set hasn’t been selected before.
|
||||
// Select the first (nearest) one.
|
||||
hitAnnotationTag = _annotationsNearbyLastClick.front();
|
||||
} else {
|
||||
// Step to the next annotation in the set.
|
||||
auto distance = std::distance(_annotationsNearbyLastClick.begin(), result);
|
||||
hitAnnotationTag = _annotationsNearbyLastClick[distance + 1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Remember the nearby annotations for the next time this method is
|
||||
|
||||
@@ -395,6 +395,16 @@ NorthOrientation Map::getNorthOrientation() const {
|
||||
return transform->getNorthOrientation();
|
||||
}
|
||||
|
||||
#pragma mark - Constrain mode
|
||||
|
||||
void Map::setConstrainMode(mbgl::ConstrainMode mode) {
|
||||
transform->setConstrainMode(mode);
|
||||
update(Update::Repaint);
|
||||
}
|
||||
|
||||
ConstrainMode Map::getConstrainMode() const {
|
||||
return transform->getConstrainMode();
|
||||
}
|
||||
|
||||
#pragma mark - Projection
|
||||
|
||||
|
||||
@@ -560,6 +560,17 @@ NorthOrientation Transform::getNorthOrientation() const {
|
||||
return state.getNorthOrientation();
|
||||
}
|
||||
|
||||
#pragma mark - Constrain mode
|
||||
|
||||
void Transform::setConstrainMode(mbgl::ConstrainMode mode) {
|
||||
state.constrainMode = mode;
|
||||
state.constrain(state.scale, state.x, state.y);
|
||||
}
|
||||
|
||||
ConstrainMode Transform::getConstrainMode() const {
|
||||
return state.getConstrainMode();
|
||||
}
|
||||
|
||||
#pragma mark - Transition
|
||||
|
||||
void Transform::startTransition(const CameraOptions& camera,
|
||||
|
||||
@@ -119,6 +119,10 @@ public:
|
||||
// North Orientation
|
||||
void setNorthOrientation(NorthOrientation);
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
|
||||
// Constrain mode
|
||||
void setConstrainMode(ConstrainMode);
|
||||
ConstrainMode getConstrainMode() const;
|
||||
|
||||
// Transitions
|
||||
bool inTransition() const;
|
||||
|
||||
@@ -81,6 +81,12 @@ double TransformState::getNorthOrientationAngle() const {
|
||||
return angleOrientation;
|
||||
}
|
||||
|
||||
#pragma mark - Constrain mode
|
||||
|
||||
ConstrainMode TransformState::getConstrainMode() const {
|
||||
return constrainMode;
|
||||
}
|
||||
|
||||
#pragma mark - Position
|
||||
|
||||
LatLng TransformState::getLatLng() const {
|
||||
@@ -354,8 +360,10 @@ void TransformState::constrain(double& scale_, double& x_, double& y_) const {
|
||||
x_ = std::max(-max_x, std::min(x_, max_x));
|
||||
}
|
||||
|
||||
double max_y = (scale_ * util::tileSize - (rotatedNorth() ? width : height)) / 2;
|
||||
y_ = std::max(-max_y, std::min(y_, max_y));
|
||||
if (constrainMode != ConstrainMode::None) {
|
||||
double max_y = (scale_ * util::tileSize - (rotatedNorth() ? width : height)) / 2;
|
||||
y_ = std::max(-max_y, std::min(y_, max_y));
|
||||
}
|
||||
}
|
||||
|
||||
void TransformState::moveLatLng(const LatLng& latLng, const PrecisionPoint& anchor) {
|
||||
|
||||
@@ -34,6 +34,9 @@ public:
|
||||
// North Orientation
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
double getNorthOrientationAngle() const;
|
||||
|
||||
// Constrain mode
|
||||
ConstrainMode getConstrainMode() const;
|
||||
|
||||
// Position
|
||||
LatLng getLatLng() const;
|
||||
|
||||
Reference in New Issue
Block a user