Cherry pick changes from mapbox-gl-native-ios. resolves #29
This commit is contained in:
41
platform/ios/platform/darwin/src/MGLEvent.h
Normal file
41
platform/ios/platform/darwin/src/MGLEvent.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#import "MGLFoundation.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Type of event used when subscribing to and unsubscribing from an `MGLObservable`.
|
||||
*/
|
||||
typedef NSString *MGLEventType NS_TYPED_EXTENSIBLE_ENUM;
|
||||
|
||||
// TODO: Doc
|
||||
FOUNDATION_EXPORT MGL_EXPORT MGLEventType const MGLEventTypeResourceRequest;
|
||||
|
||||
|
||||
/**
|
||||
Generic Event used when notifying an `MGLObserver`. This is not intended nor
|
||||
expected to be created by the application developer. It will be provided as
|
||||
part of an `MGLObservable` notification.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLEvent: NSObject
|
||||
|
||||
/// Type of an event. Matches an original event type used for a subscription.
|
||||
@property (nonatomic, readonly, copy) MGLEventType type;
|
||||
|
||||
/// Timestamp taken at the time of an event creation, relative to the Unix epoch.
|
||||
@property (nonatomic, readonly) NSTimeInterval begin;
|
||||
|
||||
/// Timestamp taken at the time of an event completion. For a non-interval
|
||||
/// (single-shot) events, migth be equal to an event's `begin` timestamp.
|
||||
/// Relative to the Unix epoch.
|
||||
@property (nonatomic, readonly) NSTimeInterval end;
|
||||
|
||||
/// Generic property for the event's data. Supported types are: `NSNumber` (int64,
|
||||
/// uint64, bool, double), `NSString`, `NSArray`, `NSDictionary`.
|
||||
@property (nonatomic, readonly, copy) id data;
|
||||
|
||||
/// Test for equality. Note this compares all properties except `data`.
|
||||
- (BOOL)isEqualToEvent:(MGLEvent *)otherEvent;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
80
platform/ios/platform/darwin/src/MGLEvent.mm
Normal file
80
platform/ios/platform/darwin/src/MGLEvent.mm
Normal file
@@ -0,0 +1,80 @@
|
||||
#import "MGLEvent_Private.h"
|
||||
#import "MGLStyleValue_Private.h"
|
||||
|
||||
const MGLEventType MGLEventTypeResourceRequest = @"resource-request";
|
||||
|
||||
#pragma mark - Event
|
||||
|
||||
@implementation MGLEvent
|
||||
|
||||
- (instancetype)init {
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithEvent:(const mbgl::ObservableEvent&)event {
|
||||
self = [super init];
|
||||
|
||||
if (!self)
|
||||
return nil;
|
||||
|
||||
// mbgl::ObservableEvent timestamps do not use the system_clock, i.e. they
|
||||
// are not relative to the Unix epoch, so we'll need to offset appropriately
|
||||
auto systemClockNow = std::chrono::system_clock::now();
|
||||
auto steadyClockNow = std::chrono::steady_clock::now();
|
||||
auto begin = std::chrono::time_point_cast<std::chrono::system_clock::duration>(systemClockNow +
|
||||
(event.begin - steadyClockNow));
|
||||
auto end = std::chrono::time_point_cast<std::chrono::system_clock::duration>(systemClockNow +
|
||||
(event.end - steadyClockNow));
|
||||
|
||||
auto beginTime = std::chrono::duration<double, std::ratio<1>>(begin.time_since_epoch()).count();
|
||||
auto endTime = std::chrono::duration<double, std::ratio<1>>(end.time_since_epoch()).count();
|
||||
|
||||
_type = (MGLEventType)[NSString stringWithUTF8String:event.type.c_str()];
|
||||
_begin = beginTime;
|
||||
_end = endTime;
|
||||
|
||||
// From value.md
|
||||
// Supported types are `int`, `uint`, `bool`, `double`, `array`, `object` and `string`.
|
||||
_data = MGLJSONObjectFromMBGLValue(event.data);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"<%@: %p; type = %@, begin = %f, end = %f, data = %@>",
|
||||
NSStringFromClass([self class]), (void *)self,
|
||||
self.type,
|
||||
self.begin,
|
||||
self.end,
|
||||
self.data];
|
||||
}
|
||||
|
||||
#pragma mark - Equality
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return self.type.hash ^ @(self.begin).hash ^ @(self.end).hash;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToEvent:(MGLEvent *)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
|
||||
// Ignore the value at this moment.
|
||||
return ((self.type == other.type) &&
|
||||
(self.begin == other.begin) &&
|
||||
(self.end == other.end));
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
|
||||
if (![other isKindOfClass:[MGLEvent class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToEvent:(MGLEvent*)other];
|
||||
}
|
||||
|
||||
@end
|
||||
11
platform/ios/platform/darwin/src/MGLEvent_Private.h
Normal file
11
platform/ios/platform/darwin/src/MGLEvent_Private.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MGLEvent.h"
|
||||
#include <mbgl/util/observable.hpp>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MGLEvent ()
|
||||
- (instancetype)initWithEvent:(const mbgl::ObservableEvent&)event;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -58,6 +58,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)setDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy;
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
/**
|
||||
Specifies the level of location accuracy the Maps SDK has permission to use.
|
||||
|
||||
@note If the value of this property is `CLAccuracyAuthorizationFullAccuracy`, you can set the
|
||||
`MGLLocationManager.desiredAccuracy` property to any value. If the value is `CLAccuracyAuthorizationReducedAccuracy`,
|
||||
setting `MGLLocationManager.desiredAccuracy` to a value other than` kCLLocationAccuracyReduced` has no effect on
|
||||
the location information.
|
||||
*/
|
||||
- (CLAccuracyAuthorization)accuracyAuthorization API_AVAILABLE(ios(14));
|
||||
#endif
|
||||
|
||||
/**
|
||||
Specifies the type of user activity associated with the location updates.
|
||||
|
||||
@@ -78,6 +90,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)setActivityType:(CLActivityType)activityType;
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
/**
|
||||
Requests the user's permission to temporarily use location update services
|
||||
with full accuracy.
|
||||
|
||||
@note If the user turned off location accuracy you may use this method to
|
||||
request full accuracy for a session.
|
||||
*/
|
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString *)purposeKey API_AVAILABLE(ios(14));
|
||||
#endif
|
||||
|
||||
@required
|
||||
|
||||
/**
|
||||
@@ -195,6 +218,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)locationManager:(id<MGLLocationManager>)manager
|
||||
didFailWithError:(nonnull NSError *)error;
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
/**
|
||||
Notifies the delegate that the location authorization status has changed.
|
||||
|
||||
@param manager The location manager reporting the change.
|
||||
*/
|
||||
- (void)locationManagerDidChangeAuthorization:(id<MGLLocationManager>)manager;
|
||||
#endif
|
||||
|
||||
@optional
|
||||
|
||||
|
||||
@@ -38,7 +38,16 @@
|
||||
}
|
||||
|
||||
- (CLAuthorizationStatus)authorizationStatus {
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
if (@available(iOS 14.0, *)) {
|
||||
return self.locationManager.authorizationStatus;
|
||||
} else {
|
||||
return kCLAuthorizationStatusNotDetermined;
|
||||
}
|
||||
#else
|
||||
return [CLLocationManager authorizationStatus];
|
||||
return [CLLocationManager authorizationStatus];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setActivityType:(CLActivityType)activityType {
|
||||
@@ -49,6 +58,23 @@
|
||||
return self.locationManager.activityType;
|
||||
}
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
- (CLAccuracyAuthorization)accuracyAuthorization {
|
||||
if (@available(iOS 14.0, *)) {
|
||||
return self.locationManager.accuracyAuthorization;
|
||||
} else {
|
||||
return CLAccuracyAuthorizationFullAccuracy;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString *)purposeKey {
|
||||
if (@available(iOS 14.0, *)) {
|
||||
[self.locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:purposeKey];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
- (void)dismissHeadingCalibrationDisplay {
|
||||
[self.locationManager dismissHeadingCalibrationDisplay];
|
||||
}
|
||||
@@ -113,4 +139,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
|
||||
[self.delegate locationManagerDidChangeAuthorization:self];
|
||||
}
|
||||
#endif
|
||||
@end
|
||||
|
||||
65
platform/ios/platform/darwin/src/MGLObserver.h
Normal file
65
platform/ios/platform/darwin/src/MGLObserver.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#import "MGLFoundation.h"
|
||||
#import "MGLEvent.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/**
|
||||
Base class for observers used to receive notifications from an `MGLObservable`.
|
||||
Subclasses should only override `-[MGLObserver notifyWithEvent:]`.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLObserver: NSObject
|
||||
|
||||
/// A unique identifier that can be used to identify an observer.
|
||||
@property (nonatomic, readonly) NSUInteger identifier;
|
||||
|
||||
/// Primary notification method.
|
||||
- (void)notifyWithEvent:(MGLEvent*)event;
|
||||
|
||||
// TODO: document
|
||||
- (BOOL)isEqualToObserver:(MGLObserver *)other;
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/**
|
||||
Protocol that yypes that wish to support subscriptions for events should conform
|
||||
to.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@protocol MGLObservable
|
||||
|
||||
/**
|
||||
Subscribes an `MGLObserver` to a provided set of event types.
|
||||
`MGLObservable` will hold a strong reference to an `MGLObserver` instance,
|
||||
therefore, in order to stop receiving notifications (and to avoid memory leaks),
|
||||
the caller must call unsubscribe with the `MGLObserver` instance used for
|
||||
the initial subscription.
|
||||
|
||||
@param observer an MGLObserver
|
||||
@param events a set of event types to subscribe to.
|
||||
*/
|
||||
- (void)subscribeForObserver:(nonnull MGLObserver *)observer
|
||||
events:(nonnull NSSet<MGLEventType> *)events;
|
||||
|
||||
/**
|
||||
Unsubscribes an `MGLObserver` from a provided set of event types.
|
||||
|
||||
@param observer an MGLObserver
|
||||
@param events a set of event types to unsubscribe from.
|
||||
*/
|
||||
- (void)unsubscribeForObserver:(nonnull MGLObserver *)observer
|
||||
events:(nonnull NSSet<MGLEventType> *)events;
|
||||
/**
|
||||
Unsubscribes an `MGLObserver` from all events (and release the strong reference).
|
||||
|
||||
@param observer an MGLObserver
|
||||
*/
|
||||
- (void)unsubscribeForObserver:(nonnull MGLObserver *)observer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
101
platform/ios/platform/darwin/src/MGLObserver.mm
Normal file
101
platform/ios/platform/darwin/src/MGLObserver.mm
Normal file
@@ -0,0 +1,101 @@
|
||||
#import "MGLObserver_Private.h"
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
#import "MGLEvent_Private.h"
|
||||
|
||||
#pragma mark - Native C++ peer object
|
||||
|
||||
namespace mbgl {
|
||||
namespace darwin {
|
||||
|
||||
void Observer::notify(const ObservableEvent& event) {
|
||||
|
||||
if (!observer) {
|
||||
MGLLogWarning(@"Platform observer has been deallocated");
|
||||
return;
|
||||
}
|
||||
|
||||
[observer notifyWithEvent:[[MGLEvent alloc] initWithEvent:event]];
|
||||
}
|
||||
|
||||
std::size_t Observer::id() const {
|
||||
if (!observer) {
|
||||
MGLLogWarning(@"Platform observer has been deallocated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(observer.identifier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Cocoa observer
|
||||
|
||||
@implementation MGLObserver
|
||||
+ (NSUInteger)nextIdentifier {
|
||||
static NSUInteger identifier;
|
||||
return ++identifier;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
MGLAssert(!_observing, @"Ensure the observer is unsubscribed before deallocating");
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (!self) return nil;
|
||||
|
||||
_identifier = [MGLObserver nextIdentifier];
|
||||
_peer = std::make_shared<mbgl::darwin::Observer>(self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)notifyWithEvent:(MGLEvent*)event {
|
||||
if (self.notificationHandler) {
|
||||
self.notificationHandler(event);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToObserver:(MGLObserver *)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
|
||||
if (self.identifier != other.identifier)
|
||||
return NO;
|
||||
|
||||
return (self.peer == other.peer);
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
|
||||
if (![other isKindOfClass:[MGLObserver class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToObserver:(MGLObserver*)other];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
// Rotate the address
|
||||
NSUInteger peerHash = reinterpret_cast<NSUInteger>(self.peer.get());
|
||||
|
||||
NSUInteger width = (sizeof(NSUInteger) * __CHAR_BIT__);
|
||||
NSUInteger shift = self.identifier % width;
|
||||
|
||||
NSUInteger newHash = (peerHash << shift) | (peerHash >> (width - shift));
|
||||
return newHash;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"<%@: %p; identifier = %lu, peer = %p, hash = %lu>",
|
||||
NSStringFromClass([self class]), (void *)self,
|
||||
(unsigned long)self.identifier,
|
||||
self.peer.get(),
|
||||
(unsigned long)[self hash]];
|
||||
}
|
||||
|
||||
@end
|
||||
40
platform/ios/platform/darwin/src/MGLObserver_Private.h
Normal file
40
platform/ios/platform/darwin/src/MGLObserver_Private.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#import <mbgl/util/observable.hpp>
|
||||
|
||||
#import "MGLObserver.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#pragma mark - Native C++ peer object
|
||||
|
||||
namespace mbgl {
|
||||
namespace darwin {
|
||||
|
||||
class Observer : public mbgl::Observer {
|
||||
public:
|
||||
Observer(MGLObserver *observer_): observer(observer_) {}
|
||||
virtual ~Observer() = default;
|
||||
virtual void notify(const ObservableEvent& event);
|
||||
virtual std::size_t id() const;
|
||||
|
||||
protected:
|
||||
|
||||
/// Cocoa observer that this adapter bridges to.
|
||||
__weak MGLObserver *observer = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@interface MGLObserver ()
|
||||
@property (nonatomic, assign) std::shared_ptr<mbgl::darwin::Observer> peer;
|
||||
|
||||
// TODO: Consider making public
|
||||
@property (nonatomic, copy) void (^notificationHandler)(MGLEvent *);
|
||||
|
||||
// Debug property used for development.
|
||||
@property (nonatomic, assign) BOOL observing;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -14,6 +14,8 @@ id MGLJSONObjectFromMBGLValue(const mbgl::Value &value) {
|
||||
return @(value);
|
||||
}, [](const int64_t value) {
|
||||
return @(value);
|
||||
}, [](const uint64_t value) {
|
||||
return @(value);
|
||||
}, [](const double value) {
|
||||
return @(value);
|
||||
}, [](const std::string &value) {
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace mbgl {
|
||||
}
|
||||
}
|
||||
|
||||
id MGLJSONObjectFromMBGLValue(const mbgl::Value &value);
|
||||
|
||||
NS_INLINE MGLTransition MGLTransitionFromOptions(const mbgl::style::TransitionOptions& options) {
|
||||
MGLTransition transition;
|
||||
transition.duration = MGLTimeIntervalFromDuration(options.duration.value_or(mbgl::Duration::zero()));
|
||||
|
||||
@@ -6,6 +6,19 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
|
||||
### Features
|
||||
|
||||
* Added `MGLLocationManager.accuracyAuthorization` and `[MGLLocationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKeyproperty:]` to support iOS 14 location accuracy privacy changes. (cherry pick from [#361](https://github.com/mapbox/mapbox-gl-native-ios/pull/361))
|
||||
* Added `[MGLLocationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKeyproperty:]` to allow developers request just-in-time full-accuracy permissions. (cherry pick from [#361](https://github.com/mapbox/mapbox-gl-native-ios/pull/361))
|
||||
* Added `[MGLLocationManagerDelegate locationManagerDidChangeAuthorization:]` to let `MGLMapView` know about privacy changes. (cherry pick from [#376](https://github.com/mapbox/mapbox-gl-native-ios/pull/376))
|
||||
* Added `[MGLMapViewDelegate mapView:didChangeLocationManagerAuthorization:]` to allow developers adjust their apps to privacy settings changes. (cherry pick from [#376](https://github.com/mapbox/mapbox-gl-native-ios/pull/376))
|
||||
* Added `MGLObserver`, `MGLObservable` and `MGLEvent` to monitor events from the map view. (cherry pick from [#358](https://github.com/mapbox/mapbox-gl-native-ios/pull/358))
|
||||
* Added an approximate user location halo when `MGLLocationManager.accuracyAuthorization` is set to `CLAccuracyAuthorizationReducedAccuracy`. (cherry pick from [#381](https://github.com/mapbox/mapbox-gl-native-ios/pull/381))
|
||||
* The `MGLAccuracyAuthorizationDescription` as element of `NSLocationTemporaryUsageDescriptionDictionary` Info.plist key can now be set to describe why you request accuracy authorization. (cherry pick from [#392](https://github.com/mapbox/mapbox-gl-native-ios/pull/392))
|
||||
* Added `[MGLMapViewDelegate mapViewStyleForDefaultUserLocationAnnotationView:]` and `MGLUserLocationAnnotationViewStyle` class to allow developers customize the default user location annotation view UI style. (cherry pick from [#403](https://github.com/mapbox/mapbox-gl-native-ios/pull/403))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed an issue that caused a crash when custom location managers did not implement `MGLLocationManager.accuracyAuthorization`. (cherry pick from [#474](https://github.com/mapbox/mapbox-gl-native-ios/pull/474))
|
||||
|
||||
### Other
|
||||
|
||||
* mapbox-gl-js submodule has been replaced with maplibre-gl-js
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<string>15256</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
|
||||
<dict>
|
||||
<key>MGLAccuracyAuthorizationDescription</key>
|
||||
<string>MapLibre requires your precise location to help you navigate the map.</string>
|
||||
</dict>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© 2014–2019 Mapbox</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#import "MBXOrnamentsViewController.h"
|
||||
|
||||
@interface MBXOrnamentsViewController ()<MGLMapViewDelegate>
|
||||
@interface MBXOrnamentsViewController ()
|
||||
|
||||
@property (nonatomic) MGLMapView *mapView;
|
||||
@property (nonatomic) NSTimer *timer;
|
||||
@@ -64,7 +64,6 @@
|
||||
zoomLevel:16
|
||||
direction:30
|
||||
animated:NO];
|
||||
mapView.delegate = self;
|
||||
mapView.showsScale = YES;
|
||||
[self.view addSubview:mapView];
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#import "MBXFrameTimeGraphView.h"
|
||||
#import "../src/MGLMapView_Experimental.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
static const CLLocationCoordinate2D WorldTourDestinations[] = {
|
||||
@@ -193,6 +192,15 @@ CLLocationCoordinate2D randomWorldCoordinate() {
|
||||
@implementation MBXSpriteBackedAnnotation
|
||||
@end
|
||||
|
||||
@interface MBXTestObserver: MGLObserver
|
||||
@end
|
||||
|
||||
@implementation MBXTestObserver
|
||||
- (void)notifyWithEvent:(MGLEvent *)event {
|
||||
NSLog(@"Received event: %@", event);
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MBXViewController () <UITableViewDelegate,
|
||||
UITableViewDataSource,
|
||||
MGLMapViewDelegate,
|
||||
@@ -213,7 +221,8 @@ CLLocationCoordinate2D randomWorldCoordinate() {
|
||||
@property (nonatomic) BOOL zoomLevelOrnamentEnabled;
|
||||
@property (nonatomic) NSMutableArray<UIWindow *> *helperWindows;
|
||||
@property (nonatomic) NSMutableArray<UIView *> *contentInsetsOverlays;
|
||||
|
||||
@property (nonatomic) MBXTestObserver *testObserver;
|
||||
@property (nonatomic, copy) void (^locationBlock)(void);
|
||||
@end
|
||||
|
||||
@interface MGLMapView (MBXViewController)
|
||||
@@ -300,6 +309,15 @@ CLLocationCoordinate2D randomWorldCoordinate() {
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
// TODO: Replace with menu implementation
|
||||
self.testObserver = [[MBXTestObserver alloc] init];
|
||||
[self.mapView subscribeForObserver:self.testObserver event:MGLEventTypeResourceRequest];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self.mapView unsubscribeForObserver:self.testObserver];
|
||||
self.testObserver = nil;
|
||||
});
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
|
||||
@@ -1952,6 +1970,12 @@ CLLocationCoordinate2D randomWorldCoordinate() {
|
||||
}
|
||||
|
||||
- (IBAction)locateUser:(id)sender
|
||||
{
|
||||
[self nextTrackingMode:sender];
|
||||
}
|
||||
|
||||
|
||||
- (void)nextTrackingMode:(id)sender
|
||||
{
|
||||
MGLUserTrackingMode nextMode;
|
||||
NSString *nextAccessibilityValue;
|
||||
@@ -2333,6 +2357,34 @@ CLLocationCoordinate2D randomWorldCoordinate() {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mapView:(nonnull MGLMapView *)mapView didChangeLocationManagerAuthorization:(nonnull id<MGLLocationManager>)manager {
|
||||
if (@available(iOS 14, *)) {
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
if (manager.authorizationStatus == kCLAuthorizationStatusDenied || manager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy) {
|
||||
[self alertAccuracyChanges];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertAccuracyChanges {
|
||||
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Mapbox GL works best with your precise location."
|
||||
message:@"You'll get turn-by-turn directions."
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:@"Turn On in Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
||||
}];
|
||||
|
||||
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"Keep Precise Location Off" style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
handler:nil];
|
||||
|
||||
[alert addAction:settingsAction];
|
||||
[alert addAction:defaultAction];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)saveCurrentMapState:(__unused NSNotification *)notification {
|
||||
|
||||
// The following properties can change after the view loads so we need to save their
|
||||
|
||||
@@ -10,6 +10,22 @@ Mapbox-hosted vector tiles and styles require an API access token, which you can
|
||||
|
||||
As an alternative, you can use `MGLAccountManager.accessToken` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.
|
||||
|
||||
## MGLAccuracyAuthorizationDescription
|
||||
|
||||
Set the Mapbox accuracy authorization description string as an element of `NSLocationTemporaryUsageDescriptionDictionary` to be used by the map to request authorization when the `MGLLocationManager.accuracyAuthorization` is set to `CLAccuracyAuthorizationReducedAccuracy`. Requesting accuracy authorization is available for devices running iOS 14.0 and above.
|
||||
|
||||
Example:
|
||||
|
||||
```xml
|
||||
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
|
||||
<dict>
|
||||
<key>MGLAccuracyAuthorizationDescription</key>
|
||||
<string>Mapbox requires your precise location to help you navigate the map.</string>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Remove `MGLAccuracyAuthorizationDescription` if you want to control when to request for accuracy authorization.
|
||||
|
||||
## MGLMapboxAPIBaseURL
|
||||
|
||||
Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used.
|
||||
@@ -47,4 +63,3 @@ At runtime, you can obtain the value of this key using the `MGLOfflineStorage.da
|
||||
Beginning in version 4.0, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`).
|
||||
|
||||
This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`.
|
||||
|
||||
|
||||
@@ -224,6 +224,22 @@
|
||||
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
|
||||
40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
|
||||
40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; };
|
||||
4BC5767B25E3C8AB006E06EB /* MGLObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767525E3C8AA006E06EB /* MGLObserver.h */; };
|
||||
4BC5767C25E3C8AB006E06EB /* MGLObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767525E3C8AA006E06EB /* MGLObserver.h */; };
|
||||
4BC5767D25E3C8AB006E06EB /* MGLEvent_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767625E3C8AB006E06EB /* MGLEvent_Private.h */; };
|
||||
4BC5767E25E3C8AB006E06EB /* MGLEvent_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767625E3C8AB006E06EB /* MGLEvent_Private.h */; };
|
||||
4BC5767F25E3C8AB006E06EB /* MGLEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5767725E3C8AB006E06EB /* MGLEvent.mm */; };
|
||||
4BC5768025E3C8AB006E06EB /* MGLEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5767725E3C8AB006E06EB /* MGLEvent.mm */; };
|
||||
4BC5768125E3C8AB006E06EB /* MGLObserver.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5767825E3C8AB006E06EB /* MGLObserver.mm */; };
|
||||
4BC5768225E3C8AB006E06EB /* MGLObserver.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5767825E3C8AB006E06EB /* MGLObserver.mm */; };
|
||||
4BC5768325E3C8AB006E06EB /* MGLEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767925E3C8AB006E06EB /* MGLEvent.h */; };
|
||||
4BC5768425E3C8AB006E06EB /* MGLEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767925E3C8AB006E06EB /* MGLEvent.h */; };
|
||||
4BC5768525E3C8AB006E06EB /* MGLObserver_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767A25E3C8AB006E06EB /* MGLObserver_Private.h */; };
|
||||
4BC5768625E3C8AB006E06EB /* MGLObserver_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5767A25E3C8AB006E06EB /* MGLObserver_Private.h */; };
|
||||
4BC5769325E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5769125E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h */; };
|
||||
4BC5769425E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC5769125E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h */; };
|
||||
4BC5769525E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5769225E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m */; };
|
||||
4BC5769625E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5769225E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m */; };
|
||||
550570C622958FB400228ECF /* MGLMapView+Impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 550570C422958FB300228ECF /* MGLMapView+Impl.mm */; };
|
||||
550570C722958FB400228ECF /* MGLMapView+Impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 550570C422958FB300228ECF /* MGLMapView+Impl.mm */; };
|
||||
550570C822958FB400228ECF /* MGLMapView+Impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 550570C522958FB400228ECF /* MGLMapView+Impl.h */; };
|
||||
@@ -907,6 +923,14 @@
|
||||
40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = "<group>"; };
|
||||
40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; };
|
||||
40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; };
|
||||
4BC5767525E3C8AA006E06EB /* MGLObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLObserver.h; sourceTree = "<group>"; };
|
||||
4BC5767625E3C8AB006E06EB /* MGLEvent_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLEvent_Private.h; sourceTree = "<group>"; };
|
||||
4BC5767725E3C8AB006E06EB /* MGLEvent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLEvent.mm; sourceTree = "<group>"; };
|
||||
4BC5767825E3C8AB006E06EB /* MGLObserver.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLObserver.mm; sourceTree = "<group>"; };
|
||||
4BC5767925E3C8AB006E06EB /* MGLEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLEvent.h; sourceTree = "<group>"; };
|
||||
4BC5767A25E3C8AB006E06EB /* MGLObserver_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLObserver_Private.h; sourceTree = "<group>"; };
|
||||
4BC5769125E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationAnnotationViewStyle.h; sourceTree = "<group>"; };
|
||||
4BC5769225E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLUserLocationAnnotationViewStyle.m; sourceTree = "<group>"; };
|
||||
550570C422958FB300228ECF /* MGLMapView+Impl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "MGLMapView+Impl.mm"; sourceTree = "<group>"; };
|
||||
550570C522958FB400228ECF /* MGLMapView+Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+Impl.h"; sourceTree = "<group>"; };
|
||||
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
@@ -1894,6 +1918,12 @@
|
||||
1F6A82A021360F9C00BA5B41 /* MGLLoggingConfiguration.h */,
|
||||
CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */,
|
||||
1F6A82A62138871900BA5B41 /* MGLLoggingConfiguration_Private.h */,
|
||||
4BC5767625E3C8AB006E06EB /* MGLEvent_Private.h */,
|
||||
4BC5767925E3C8AB006E06EB /* MGLEvent.h */,
|
||||
4BC5767725E3C8AB006E06EB /* MGLEvent.mm */,
|
||||
4BC5767A25E3C8AB006E06EB /* MGLObserver_Private.h */,
|
||||
4BC5767525E3C8AA006E06EB /* MGLObserver.h */,
|
||||
4BC5767825E3C8AB006E06EB /* MGLObserver.mm */,
|
||||
);
|
||||
name = Foundation;
|
||||
path = ../darwin/src;
|
||||
@@ -1919,6 +1949,8 @@
|
||||
5580B45A229570A10091291B /* MGLMapView+OpenGL.mm */,
|
||||
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
|
||||
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
|
||||
4BC5769125E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h */,
|
||||
4BC5769225E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m */,
|
||||
);
|
||||
name = Kit;
|
||||
path = src;
|
||||
@@ -2182,6 +2214,7 @@
|
||||
357FE2DD1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */,
|
||||
07D947531F67488E00E37934 /* MGLComputedShapeSource_Private.h in Headers */,
|
||||
4BC5768325E3C8AB006E06EB /* MGLEvent.h in Headers */,
|
||||
9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */,
|
||||
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */,
|
||||
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
|
||||
@@ -2195,6 +2228,7 @@
|
||||
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
|
||||
74CB5EBF219B280400102936 /* MGLHeatmapStyleLayer_Private.h in Headers */,
|
||||
1FC4817D2098CBC0000D09B4 /* NSPredicate+MGLPrivateAdditions.h in Headers */,
|
||||
4BC5767B25E3C8AB006E06EB /* MGLObserver.h in Headers */,
|
||||
1F2B94C0221636D900210640 /* MGLNetworkConfiguration_Private.h in Headers */,
|
||||
353AFA141D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */,
|
||||
DA8848531CBAFB9800AB86E3 /* MGLCompactCalloutView.h in Headers */,
|
||||
@@ -2239,6 +2273,7 @@
|
||||
CAFB3C14234505D500399265 /* MGLMapSnapshotter_Private.h in Headers */,
|
||||
1FCAE2A220B872A400C577DD /* MGLLocationManager.h in Headers */,
|
||||
DACA86262019218600E9693A /* MGLRasterDEMSource.h in Headers */,
|
||||
4BC5769325E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h in Headers */,
|
||||
353933F81D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
|
||||
92F2C3ED1F0E3C3A00268EC0 /* MGLRendererFrontend.h in Headers */,
|
||||
DAAF722D1DA903C700312FA4 /* MGLStyleValue_Private.h in Headers */,
|
||||
@@ -2300,6 +2335,7 @@
|
||||
DA72620B1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */,
|
||||
404C26E71D89C55D000AA13D /* MGLTileSource_Private.h in Headers */,
|
||||
DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */,
|
||||
4BC5767D25E3C8AB006E06EB /* MGLEvent_Private.h in Headers */,
|
||||
359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */,
|
||||
404C26E21D89B877000AA13D /* MGLTileSource.h in Headers */,
|
||||
DA8847FD1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h in Headers */,
|
||||
@@ -2308,6 +2344,7 @@
|
||||
350098BB1D480108004B2AF0 /* MGLVectorTileSource.h in Headers */,
|
||||
DA8847F61CBAFA5100AB86E3 /* MGLOfflineStorage.h in Headers */,
|
||||
DAD1656E1CF41981001FF4B9 /* MGLFeature_Private.h in Headers */,
|
||||
4BC5768525E3C8AB006E06EB /* MGLObserver_Private.h in Headers */,
|
||||
DA88483C1CBAFB8500AB86E3 /* MGLMapView.h in Headers */,
|
||||
3EA9363147E77DD29FA06063 /* MGLRendererConfiguration.h in Headers */,
|
||||
550570C822958FB400228ECF /* MGLMapView+Impl.h in Headers */,
|
||||
@@ -2340,6 +2377,7 @@
|
||||
3566C7671D4A77BA008152BC /* MGLShapeSource.h in Headers */,
|
||||
DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
|
||||
967C864C210A9D3C004DF794 /* UIDevice+MGLAdditions.h in Headers */,
|
||||
4BC5768425E3C8AB006E06EB /* MGLEvent.h in Headers */,
|
||||
404C26E31D89B877000AA13D /* MGLTileSource.h in Headers */,
|
||||
96E516F6200059EC00A02306 /* MGLRendererFrontend.h in Headers */,
|
||||
071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */,
|
||||
@@ -2353,6 +2391,7 @@
|
||||
96E516EF2000594F00A02306 /* NSArray+MGLAdditions.h in Headers */,
|
||||
96E516F12000596800A02306 /* NSString+MGLAdditions.h in Headers */,
|
||||
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */,
|
||||
4BC5767C25E3C8AB006E06EB /* MGLObserver.h in Headers */,
|
||||
CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
|
||||
DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */,
|
||||
DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */,
|
||||
@@ -2397,6 +2436,7 @@
|
||||
1F2B94C1221636D900210640 /* MGLNetworkConfiguration_Private.h in Headers */,
|
||||
35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
|
||||
96E516F32000597100A02306 /* NSDictionary+MGLAdditions.h in Headers */,
|
||||
4BC5769425E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h in Headers */,
|
||||
1FCAE2A920B88B3800C577DD /* MGLLocationManager_Private.h in Headers */,
|
||||
96E516F02000595800A02306 /* NSBundle+MGLAdditions.h in Headers */,
|
||||
96E516F920005A3500A02306 /* MGLFaux3DUserLocationAnnotationView.h in Headers */,
|
||||
@@ -2458,6 +2498,7 @@
|
||||
96E516E82000560B00A02306 /* MGLAnnotationContainerView_Private.h in Headers */,
|
||||
35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */,
|
||||
DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */,
|
||||
4BC5767E25E3C8AB006E06EB /* MGLEvent_Private.h in Headers */,
|
||||
96E516FC20005A4400A02306 /* MGLUserLocationHeadingIndicator.h in Headers */,
|
||||
1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */,
|
||||
DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */,
|
||||
@@ -2466,6 +2507,7 @@
|
||||
DABFB86A1CBE99E500D62B32 /* MGLStyle.h in Headers */,
|
||||
DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */,
|
||||
96E516E12000551100A02306 /* MGLMultiPoint_Private.h in Headers */,
|
||||
4BC5768625E3C8AB006E06EB /* MGLObserver_Private.h in Headers */,
|
||||
3EA934623AD0000B7D99C3FB /* MGLRendererConfiguration.h in Headers */,
|
||||
DACA86272019218600E9693A /* MGLRasterDEMSource.h in Headers */,
|
||||
9621F2502091020E005B3800 /* NSExpression+MGLAdditions.h in Headers */,
|
||||
@@ -3055,6 +3097,7 @@
|
||||
DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */,
|
||||
35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
|
||||
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
|
||||
4BC5768125E3C8AB006E06EB /* MGLObserver.mm in Sources */,
|
||||
8989B17E201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
|
||||
353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
1FCAE2A420B872A400C577DD /* MGLLocationManager.m in Sources */,
|
||||
@@ -3062,6 +3105,7 @@
|
||||
DA8848241CBAFA6200AB86E3 /* MGLOfflineStorage.mm in Sources */,
|
||||
DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */,
|
||||
4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
|
||||
4BC5769525E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m in Sources */,
|
||||
35136D3F1D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */,
|
||||
DA704CC41F65A475004B3F28 /* MGLMapAccessibilityElement.mm in Sources */,
|
||||
DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
|
||||
@@ -3070,6 +3114,7 @@
|
||||
DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */,
|
||||
35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
|
||||
3EA93369F61CF70AFA50465D /* MGLRendererConfiguration.m in Sources */,
|
||||
4BC5767F25E3C8AB006E06EB /* MGLEvent.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3151,6 +3196,7 @@
|
||||
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
|
||||
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
|
||||
8989B17F201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
|
||||
4BC5768225E3C8AB006E06EB /* MGLObserver.mm in Sources */,
|
||||
353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
|
||||
1FCAE2A520B872A400C577DD /* MGLLocationManager.m in Sources */,
|
||||
@@ -3158,6 +3204,7 @@
|
||||
4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
|
||||
35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */,
|
||||
DA704CC51F65A475004B3F28 /* MGLMapAccessibilityElement.mm in Sources */,
|
||||
4BC5769625E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m in Sources */,
|
||||
DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
|
||||
DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */,
|
||||
3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
|
||||
@@ -3166,6 +3213,7 @@
|
||||
35CE61851D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
|
||||
DAA4E4241CBB730400178DFB /* MGLPolyline.mm in Sources */,
|
||||
3EA9366247780E4F252652A8 /* MGLRendererConfiguration.m in Sources */,
|
||||
4BC5768025E3C8AB006E06EB /* MGLEvent.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#import "MGLFaux3DUserLocationAnnotationView.h"
|
||||
|
||||
#import "MGLMapView.h"
|
||||
#import "MGLMapViewDelegate.h"
|
||||
#import "MGLUserLocation.h"
|
||||
#import "MGLUserLocationHeadingIndicator.h"
|
||||
#import "MGLUserLocationHeadingArrowLayer.h"
|
||||
#import "MGLUserLocationHeadingBeamLayer.h"
|
||||
#import "MGLLocationManager_Private.h"
|
||||
#import "MGLUserLocationAnnotationViewStyle.h"
|
||||
|
||||
const CGFloat MGLUserLocationAnnotationDotSize = 22.0;
|
||||
const CGFloat MGLUserLocationAnnotationHaloSize = 115.0;
|
||||
@@ -14,9 +17,12 @@ const CGFloat MGLUserLocationAnnotationArrowSize = MGLUserLocationAnnotationPuck
|
||||
|
||||
const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
|
||||
const CGFloat MGLUserLocationApproximateZoomThreshold = 7.0;
|
||||
|
||||
@implementation MGLFaux3DUserLocationAnnotationView
|
||||
{
|
||||
BOOL _puckModeActivated;
|
||||
BOOL _approximateModeActivated;
|
||||
|
||||
CALayer *_puckDot;
|
||||
CAShapeLayer *_puckArrow;
|
||||
@@ -27,6 +33,8 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
CALayer *_dotLayer;
|
||||
CALayer *_haloLayer;
|
||||
|
||||
CALayer *_approximateLayer;
|
||||
|
||||
CLLocationDirection _oldHeadingAccuracy;
|
||||
CLLocationAccuracy _oldHorizontalAccuracy;
|
||||
double _oldZoom;
|
||||
@@ -49,28 +57,77 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
|
||||
if (CLLocationCoordinate2DIsValid(self.userLocation.coordinate))
|
||||
{
|
||||
(self.mapView.userTrackingMode == MGLUserTrackingModeFollowWithCourse) ? [self drawPuck] : [self drawDot];
|
||||
[self updatePitch];
|
||||
if (@available(iOS 14, *)) {
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
if (![self.mapView.locationManager respondsToSelector:@selector(accuracyAuthorization)] ||
|
||||
self.mapView.locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy) {
|
||||
[self drawPreciseLocationPuck];
|
||||
} else {
|
||||
[self drawApproximate];
|
||||
[self updatePitch];
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
[self drawPreciseLocationPuck];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawPreciseLocationPuck {
|
||||
if (_approximateModeActivated) {
|
||||
[_approximateLayer removeFromSuperlayer];
|
||||
_approximateLayer = nil;
|
||||
|
||||
_approximateModeActivated = NO;
|
||||
}
|
||||
(self.mapView.userTrackingMode == MGLUserTrackingModeFollowWithCourse) ? [self drawPuck] : [self drawDot];
|
||||
[self updatePitch];
|
||||
_haloLayer.hidden = ! CLLocationCoordinate2DIsValid(self.mapView.userLocation.coordinate) || self.mapView.userLocation.location.horizontalAccuracy > 10;
|
||||
}
|
||||
|
||||
|
||||
- (void)setTintColor:(UIColor *)tintColor
|
||||
{
|
||||
CGColorRef newTintColor = [tintColor CGColor];
|
||||
|
||||
UIColor *puckArrowFillColor = tintColor;
|
||||
UIColor *puckArrowStrokeColor = tintColor;
|
||||
|
||||
UIColor *approximateFillColor = tintColor;
|
||||
|
||||
UIColor *accuracyFillColor = tintColor;
|
||||
UIColor *haloFillColor = tintColor;
|
||||
UIColor *dotFillColor = tintColor;
|
||||
UIColor *headingFillColor = tintColor;
|
||||
|
||||
if ([self.mapView.delegate respondsToSelector:@selector(mapViewStyleForDefaultUserLocationAnnotationView:)]) {
|
||||
MGLUserLocationAnnotationViewStyle *style = [self.mapView.delegate mapViewStyleForDefaultUserLocationAnnotationView:self.mapView];
|
||||
|
||||
puckArrowFillColor = style.puckArrowFillColor ? style.puckArrowFillColor : puckArrowFillColor;
|
||||
|
||||
if (@available(iOS 14, *)) {
|
||||
approximateFillColor = style.approximateHaloFillColor ? style.approximateHaloFillColor : approximateFillColor;
|
||||
}
|
||||
|
||||
haloFillColor = style.haloFillColor ? style.haloFillColor : haloFillColor;
|
||||
dotFillColor = style.puckFillColor ? style.puckFillColor : dotFillColor;
|
||||
headingFillColor = style.puckFillColor ? style.puckFillColor : headingFillColor;
|
||||
}
|
||||
|
||||
if (_puckModeActivated)
|
||||
{
|
||||
_puckArrow.fillColor = newTintColor;
|
||||
_puckArrow.strokeColor = newTintColor;
|
||||
_puckArrow.fillColor = [puckArrowFillColor CGColor];
|
||||
_puckArrow.strokeColor = [puckArrowStrokeColor CGColor];
|
||||
}
|
||||
else if (_approximateModeActivated)
|
||||
{
|
||||
_approximateLayer.backgroundColor = [approximateFillColor CGColor];
|
||||
}
|
||||
else
|
||||
{
|
||||
_accuracyRingLayer.backgroundColor = newTintColor;
|
||||
_haloLayer.backgroundColor = newTintColor;
|
||||
_dotLayer.backgroundColor = newTintColor;
|
||||
[_headingIndicatorLayer updateTintColor:newTintColor];
|
||||
_accuracyRingLayer.backgroundColor = [accuracyFillColor CGColor];
|
||||
_haloLayer.backgroundColor = [haloFillColor CGColor];
|
||||
_dotLayer.backgroundColor = [dotFillColor CGColor];
|
||||
[_headingIndicatorLayer updateTintColor:[headingFillColor CGColor]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,14 +203,26 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
[self updateFrameWithSize:MGLUserLocationAnnotationPuckSize];
|
||||
}
|
||||
|
||||
UIColor *arrowColor = self.mapView.tintColor;
|
||||
UIColor *puckShadowColor = UIColor.blackColor;
|
||||
CGFloat shadowOpacity = 0.25;
|
||||
|
||||
|
||||
if ([self.mapView.delegate respondsToSelector:@selector(mapViewStyleForDefaultUserLocationAnnotationView:)]) {
|
||||
MGLUserLocationAnnotationViewStyle *style = [self.mapView.delegate mapViewStyleForDefaultUserLocationAnnotationView:self.mapView];
|
||||
arrowColor = style.puckArrowFillColor ? style.puckArrowFillColor : arrowColor;
|
||||
puckShadowColor = style.puckShadowColor ? style.puckShadowColor : puckShadowColor;
|
||||
shadowOpacity = style.puckShadowOpacity;
|
||||
}
|
||||
|
||||
// background dot (white with black shadow)
|
||||
//
|
||||
if ( ! _puckDot)
|
||||
{
|
||||
_puckDot = [self circleLayerWithSize:MGLUserLocationAnnotationPuckSize];
|
||||
_puckDot.backgroundColor = [[UIColor whiteColor] CGColor];
|
||||
_puckDot.shadowColor = [[UIColor blackColor] CGColor];
|
||||
_puckDot.shadowOpacity = 0.25;
|
||||
_puckDot.shadowColor = [puckShadowColor CGColor];
|
||||
_puckDot.shadowOpacity = shadowOpacity;
|
||||
_puckDot.shadowPath = [[UIBezierPath bezierPathWithOvalInRect:_puckDot.bounds] CGPath];
|
||||
|
||||
if (self.mapView.camera.pitch)
|
||||
@@ -175,7 +244,7 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
{
|
||||
_puckArrow = [CAShapeLayer layer];
|
||||
_puckArrow.path = [[self puckArrow] CGPath];
|
||||
_puckArrow.fillColor = [self.mapView.tintColor CGColor];
|
||||
_puckArrow.fillColor = [arrowColor CGColor];
|
||||
_puckArrow.bounds = CGRectMake(0, 0, round(MGLUserLocationAnnotationArrowSize), round(MGLUserLocationAnnotationArrowSize));
|
||||
_puckArrow.position = CGPointMake(CGRectGetMidX(super.bounds), CGRectGetMidY(super.bounds));
|
||||
_puckArrow.shouldRasterize = YES;
|
||||
@@ -228,6 +297,20 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
[self updateFrameWithSize:MGLUserLocationAnnotationDotSize];
|
||||
}
|
||||
|
||||
|
||||
UIColor *haloColor = self.mapView.tintColor;
|
||||
UIColor *puckBackgroundColor = self.mapView.tintColor;
|
||||
UIColor *puckShadowColor = UIColor.blackColor;
|
||||
CGFloat shadowOpacity = 0.25;
|
||||
|
||||
if ([self.mapView.delegate respondsToSelector:@selector(mapViewStyleForDefaultUserLocationAnnotationView:)]) {
|
||||
MGLUserLocationAnnotationViewStyle *style = [self.mapView.delegate mapViewStyleForDefaultUserLocationAnnotationView:self.mapView];
|
||||
haloColor = style.haloFillColor ? style.haloFillColor : haloColor;
|
||||
puckBackgroundColor = style.puckFillColor ? style.puckFillColor : puckBackgroundColor;
|
||||
puckShadowColor = style.puckShadowColor ? style.puckShadowColor : puckShadowColor;
|
||||
shadowOpacity = style.puckShadowOpacity;
|
||||
}
|
||||
|
||||
// heading indicator (tinted, beam or arrow)
|
||||
//
|
||||
BOOL headingTrackingModeEnabled = self.mapView.userTrackingMode == MGLUserTrackingModeFollowWithHeading;
|
||||
@@ -251,11 +334,13 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
if (headingTrackingModeEnabled)
|
||||
{
|
||||
_headingIndicatorLayer = [[MGLUserLocationHeadingBeamLayer alloc] initWithUserLocationAnnotationView:self];
|
||||
[_headingIndicatorLayer updateTintColor:[haloColor CGColor]];
|
||||
[self.layer insertSublayer:_headingIndicatorLayer below:_dotBorderLayer];
|
||||
}
|
||||
else
|
||||
{
|
||||
_headingIndicatorLayer = [[MGLUserLocationHeadingArrowLayer alloc] initWithUserLocationAnnotationView:self];
|
||||
[_headingIndicatorLayer updateTintColor:[puckBackgroundColor CGColor]];
|
||||
[self.layer addSublayer:_headingIndicatorLayer];
|
||||
_headingIndicatorLayer.zPosition = 1;
|
||||
}
|
||||
@@ -351,7 +436,7 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
if ( ! _haloLayer)
|
||||
{
|
||||
_haloLayer = [self circleLayerWithSize:MGLUserLocationAnnotationHaloSize];
|
||||
_haloLayer.backgroundColor = [self.mapView.tintColor CGColor];
|
||||
_haloLayer.backgroundColor = [haloColor CGColor];
|
||||
_haloLayer.allowsGroupOpacity = NO;
|
||||
_haloLayer.zPosition = -0.1f;
|
||||
|
||||
@@ -381,8 +466,8 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
{
|
||||
_dotBorderLayer = [self circleLayerWithSize:MGLUserLocationAnnotationDotSize];
|
||||
_dotBorderLayer.backgroundColor = [[UIColor whiteColor] CGColor];
|
||||
_dotBorderLayer.shadowColor = [[UIColor blackColor] CGColor];
|
||||
_dotBorderLayer.shadowOpacity = 0.25;
|
||||
_dotBorderLayer.shadowColor = [puckShadowColor CGColor];
|
||||
_dotBorderLayer.shadowOpacity = shadowOpacity;
|
||||
_dotBorderLayer.shadowPath = [[UIBezierPath bezierPathWithOvalInRect:_dotBorderLayer.bounds] CGPath];
|
||||
|
||||
if (self.mapView.camera.pitch)
|
||||
@@ -403,7 +488,7 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
if ( ! _dotLayer)
|
||||
{
|
||||
_dotLayer = [self circleLayerWithSize:MGLUserLocationAnnotationDotSize * 0.75];
|
||||
_dotLayer.backgroundColor = [self.mapView.tintColor CGColor];
|
||||
_dotLayer.backgroundColor = [puckBackgroundColor CGColor];
|
||||
|
||||
// set defaults for the animations
|
||||
CAAnimationGroup *animationGroup = [self loopingAnimationGroupWithDuration:1.5];
|
||||
@@ -435,6 +520,85 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawApproximate
|
||||
{
|
||||
if ( ! _approximateModeActivated)
|
||||
{
|
||||
self.layer.sublayers = nil;
|
||||
|
||||
_headingIndicatorLayer = nil;
|
||||
_dotBorderLayer = nil;
|
||||
_dotLayer = nil;
|
||||
_accuracyRingLayer = nil;
|
||||
_haloLayer = nil;
|
||||
_puckDot = nil;
|
||||
_puckArrow = nil;
|
||||
|
||||
_approximateModeActivated = YES;
|
||||
}
|
||||
|
||||
UIColor *backgroundColor = self.mapView.tintColor;
|
||||
UIColor *strokeColor = UIColor.blackColor;
|
||||
CGFloat borderSize = 2.0;
|
||||
CGFloat opacity = 0.25;
|
||||
|
||||
if ([self.mapView.delegate respondsToSelector:@selector(mapViewStyleForDefaultUserLocationAnnotationView:)]) {
|
||||
MGLUserLocationAnnotationViewStyle *style = [self.mapView.delegate mapViewStyleForDefaultUserLocationAnnotationView:self.mapView];
|
||||
if (@available(iOS 14, *)) {
|
||||
backgroundColor = style.approximateHaloFillColor ? style.approximateHaloFillColor : backgroundColor;
|
||||
strokeColor = style.approximateHaloBorderColor ? style.approximateHaloBorderColor : strokeColor;
|
||||
opacity = style.approximateHaloOpacity;
|
||||
borderSize = style.approximateHaloBorderWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// update approximate ring (if zoom or horizontal accuracy have changed)
|
||||
if (_approximateLayer && (_oldZoom != self.mapView.zoomLevel || _oldHorizontalAccuracy != self.userLocation.location.horizontalAccuracy))
|
||||
{
|
||||
CGFloat borderWidth = 2;
|
||||
if (self.mapView.zoomLevel < MGLUserLocationApproximateZoomThreshold) {
|
||||
borderSize = 3;
|
||||
}
|
||||
_approximateLayer.borderWidth = borderSize;
|
||||
|
||||
if (self.mapView.zoomLevel >= MGLUserLocationApproximateZoomThreshold) {
|
||||
CGFloat accuracyRingSize = [self calculateAccuracyRingSize];
|
||||
|
||||
_approximateLayer.hidden = NO;
|
||||
|
||||
// disable implicit animation of the accuracy ring, unless triggered by a change in accuracy
|
||||
BOOL shouldDisableActions = _oldHorizontalAccuracy == self.userLocation.location.horizontalAccuracy;
|
||||
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:shouldDisableActions];
|
||||
|
||||
_approximateLayer.bounds = CGRectMake(0, 0, accuracyRingSize, accuracyRingSize);
|
||||
_approximateLayer.cornerRadius = accuracyRingSize / 2.0;
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
// store accuracy and zoom so we're not redrawing unchanged location updates
|
||||
_oldHorizontalAccuracy = self.userLocation.location.horizontalAccuracy;
|
||||
_oldZoom = self.mapView.zoomLevel;
|
||||
}
|
||||
|
||||
// approximate ring
|
||||
if ( ! _approximateLayer && self.userLocation.location.horizontalAccuracy)
|
||||
{
|
||||
CGFloat accuracyRingSize = [self calculateAccuracyRingSize];
|
||||
_approximateLayer = [self circleLayerWithSize:accuracyRingSize];
|
||||
approximateLayer.backgroundColor = [backgroundColor CGColor];
|
||||
_approximateLayer.opacity = opacity;
|
||||
_approximateLayer.shouldRasterize = NO;
|
||||
_approximateLayer.allowsGroupOpacity = NO;
|
||||
_approximateLayer.borderWidth = borderSize;
|
||||
_approximateLayer.borderColor = [strokeColor CGColor];
|
||||
|
||||
[self.layer addSublayer:_approximateLayer];
|
||||
}
|
||||
}
|
||||
|
||||
- (CALayer *)circleLayerWithSize:(CGFloat)layerSize
|
||||
{
|
||||
layerSize = round(layerSize);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#import "MGLMapCamera.h"
|
||||
#import "MGLTypes.h"
|
||||
#import "MGLStyle.h"
|
||||
#import "MGLObserver.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -188,7 +189,7 @@ FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const MGLUserLocationAnnotationTyp
|
||||
Simple map view</a> example to learn how to initialize a basic `MGLMapView`.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLMapView : UIView <MGLStylable>
|
||||
@interface MGLMapView : UIView <MGLStylable, MGLObservable>
|
||||
|
||||
#pragma mark Creating Instances
|
||||
|
||||
@@ -2002,6 +2003,14 @@ MGL_EXPORT
|
||||
*/
|
||||
@property (nonatomic) MGLMapDebugMaskOptions debugMask;
|
||||
|
||||
/**
|
||||
:nodoc:
|
||||
Convenience method for subscribing to a single event. See `-[MGLObservable
|
||||
subscribeForObserver:events:]`.
|
||||
*/
|
||||
- (void)subscribeForObserver:(nonnull MGLObserver *)observer
|
||||
event:(nonnull MGLEventType)event;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
#import "MGLNetworkConfiguration_Private.h"
|
||||
#import "MGLReachability.h"
|
||||
#import "MGLObserver_Private.h"
|
||||
#import "MGLEvent_Private.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
@@ -277,6 +279,8 @@ public:
|
||||
@property (nonatomic, assign) UIEdgeInsets safeMapViewContentInsets;
|
||||
@property (nonatomic, strong) NSNumber *automaticallyAdjustContentInsetHolder;
|
||||
|
||||
@property (nonatomic) NSMutableSet<MGLObserver *> *observerCache;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLMapView
|
||||
@@ -517,6 +521,8 @@ public:
|
||||
_annotationViewReuseQueueByIdentifier = [NSMutableDictionary dictionary];
|
||||
_selectedAnnotationTag = MGLAnnotationTagNotFound;
|
||||
_annotationsNearbyLastTap = {};
|
||||
|
||||
_observerCache = [NSMutableSet set];
|
||||
|
||||
// TODO: This warning should be removed when automaticallyAdjustsScrollViewInsets is removed from
|
||||
// the UIViewController api.
|
||||
@@ -5417,6 +5423,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)accuracyDescriptionString {
|
||||
NSDictionary *dictionary = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationTemporaryUsageDescriptionDictionary"];
|
||||
return dictionary[@"MGLAccuracyAuthorizationDescription"];
|
||||
}
|
||||
|
||||
- (void)setShowsUserLocation:(BOOL)showsUserLocation
|
||||
{
|
||||
MGLLogDebug(@"Setting showsUserLocation: %@", MGLStringFromBOOL(showsUserLocation));
|
||||
@@ -5975,6 +5986,47 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (void)locationManagerDidChangeAuthorization:(id<MGLLocationManager>)manager
|
||||
{
|
||||
if (![self shouldShowLocationDotBasedOnCurrentLocationPermissions])
|
||||
{
|
||||
[self.userLocationAnnotationView removeFromSuperview];
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
[self.locationManager stopUpdatingHeading];
|
||||
} else {
|
||||
if (@available(iOS 14, *)) {
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
||||
if (self.userTrackingMode != MGLUserTrackingModeNone &&
|
||||
[manager respondsToSelector:@selector(authorizationStatus)] &&
|
||||
(manager.authorizationStatus != kCLAuthorizationStatusRestricted ||
|
||||
manager.authorizationStatus != kCLAuthorizationStatusAuthorizedAlways ||
|
||||
manager.authorizationStatus != kCLAuthorizationStatusAuthorizedWhenInUse) &&
|
||||
[manager respondsToSelector:@selector(accuracyAuthorization)] &&
|
||||
manager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy &&
|
||||
[self accuracyDescriptionString] != nil ) {
|
||||
[self.locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:@"MGLAccuracyAuthorizationDescription"];
|
||||
} else {
|
||||
[self validateLocationServices];
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
[self validateLocationServices];
|
||||
}
|
||||
}
|
||||
|
||||
if (@available(iOS 14, *)) {
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:didChangeLocationManagerAuthorization:)]) {
|
||||
[self.delegate mapView:self didChangeLocationManagerAuthorization:manager];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldShowLocationDotBasedOnCurrentLocationPermissions
|
||||
{
|
||||
return self.locationManager && (self.locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedAlways
|
||||
|| self.locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse);
|
||||
}
|
||||
|
||||
- (void)updateHeadingForDeviceOrientation
|
||||
{
|
||||
if (self.locationManager)
|
||||
@@ -6840,6 +6892,41 @@ public:
|
||||
return _annotationViewReuseQueueByIdentifier[identifier];
|
||||
}
|
||||
|
||||
#pragma mark - MGLObservable methods -
|
||||
|
||||
static std::vector<std::string> vectorOfStringsFromSet(NSSet<NSString *> *setOfStrings) {
|
||||
__block std::vector<std::string> strings;
|
||||
strings.reserve(setOfStrings.count);
|
||||
[setOfStrings enumerateObjectsUsingBlock:^(NSString * _Nonnull text, BOOL * _Nonnull stop) {
|
||||
strings.push_back(text.UTF8String);
|
||||
}];
|
||||
return strings;
|
||||
}
|
||||
|
||||
// Convenience method
|
||||
- (void)subscribeForObserver:(nonnull MGLObserver *)observer event:(nonnull MGLEventType)event {
|
||||
[self subscribeForObserver:observer events:[NSSet setWithObject:event]];
|
||||
}
|
||||
|
||||
- (void)subscribeForObserver:(MGLObserver *)observer events:(nonnull NSSet<MGLEventType> *)events {
|
||||
observer.observing = YES;
|
||||
[self.observerCache addObject:observer];
|
||||
|
||||
auto eventTypes = vectorOfStringsFromSet(events);
|
||||
self.mbglMap.subscribe(observer.peer, eventTypes);
|
||||
}
|
||||
|
||||
- (void)unsubscribeForObserver:(MGLObserver *)observer events:(nonnull NSSet<MGLEventType> *)events {
|
||||
auto eventTypes = vectorOfStringsFromSet(events);
|
||||
self.mbglMap.unsubscribe(observer.peer, eventTypes);
|
||||
}
|
||||
|
||||
- (void)unsubscribeForObserver:(MGLObserver *)observer {
|
||||
self.mbglMap.unsubscribe(observer.peer);
|
||||
[self.observerCache removeObject:observer];
|
||||
observer.observing = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - IBAdditions methods
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class MGLMapView;
|
||||
@class MGLUserLocationAnnotationViewStyle;
|
||||
|
||||
/**
|
||||
The `MGLMapViewDelegate` protocol defines a set of optional methods that you
|
||||
@@ -313,6 +314,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)mapViewDidStopLocatingUser:(MGLMapView *)mapView;
|
||||
|
||||
/**
|
||||
Asks the delegate styling options for each default user location annotation view.
|
||||
|
||||
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 is tracking the user’s location.
|
||||
*/
|
||||
- (MGLUserLocationAnnotationViewStyle *)mapViewStyleForDefaultUserLocationAnnotationView:(MGLMapView *)mapView NS_SWIFT_NAME(mapView(styleForDefaultUserLocationAnnotationView:));
|
||||
|
||||
/**
|
||||
Tells the delegate that the location of the user was updated.
|
||||
|
||||
@@ -368,6 +379,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (CGPoint)mapViewUserLocationAnchorPoint:(MGLMapView *)mapView;
|
||||
|
||||
/**
|
||||
Tells the delegate that the map's location updates accuracy authorization has changed.
|
||||
|
||||
This method is called after the user changes location accuracy authorization when
|
||||
requesting location permissions or in privacy settings.
|
||||
|
||||
@param mapView The map view that changed its location accuracy authorization.
|
||||
@param manager The location manager reporting the update.
|
||||
|
||||
*/
|
||||
- (void)mapView:(MGLMapView *)mapView didChangeLocationManagerAuthorization:(id<MGLLocationManager>)manager API_AVAILABLE(ios(14));
|
||||
|
||||
#pragma mark Managing the Appearance of Annotations
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "MGLFoundation.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
A class containing information about the default User Location annotation view style.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLUserLocationAnnotationViewStyle : NSObject
|
||||
|
||||
/**
|
||||
The fill color for the puck view.
|
||||
*/
|
||||
@property (nonatomic) UIColor *puckFillColor;
|
||||
/**
|
||||
The shadow color for the puck view.
|
||||
*/
|
||||
@property (nonatomic) UIColor *puckShadowColor;
|
||||
/**
|
||||
The shadow opacity for the puck view.
|
||||
Set any value between 0.0 and 1.0.
|
||||
The default value of this property is equal to `0.25`
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat puckShadowOpacity;
|
||||
/**
|
||||
The fill color for the arrow puck.
|
||||
*/
|
||||
@property (nonatomic) UIColor *puckArrowFillColor;
|
||||
/**
|
||||
The fill color for the puck view.
|
||||
*/
|
||||
@property (nonatomic) UIColor *haloFillColor;
|
||||
/**
|
||||
The halo fill color for the approximate view.
|
||||
*/
|
||||
@property (nonatomic) UIColor *approximateHaloFillColor API_AVAILABLE(ios(14));
|
||||
/**
|
||||
The halo border color for the approximate view.
|
||||
*/
|
||||
@property (nonatomic) UIColor *approximateHaloBorderColor API_AVAILABLE(ios(14));
|
||||
/**
|
||||
The halo border width for the approximate view.
|
||||
The default value of this property is equal to `2.0`
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat approximateHaloBorderWidth API_AVAILABLE(ios(14));
|
||||
/**
|
||||
The halo opacity for the approximate view.
|
||||
Set any value between 0.0 and 1.0
|
||||
The default value of this property is equal to `0.15`
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat approximateHaloOpacity API_AVAILABLE(ios(14));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,62 @@
|
||||
#import "MGLUserLocationAnnotationViewStyle.h"
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
|
||||
@implementation MGLUserLocationAnnotationViewStyle
|
||||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
self.puckShadowOpacity = 0.25;
|
||||
if (@available(iOS 14, *)) {
|
||||
self.approximateHaloBorderWidth = 2.0;
|
||||
self.approximateHaloOpacity = 0.15;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setPuckFillColor:(UIColor *)puckFillColor {
|
||||
MGLLogDebug(@"Setting puckFillColor: %@", puckFillColor);
|
||||
_puckFillColor = puckFillColor;
|
||||
}
|
||||
|
||||
- (void)setPuckShadowColor:(UIColor *)puckShadowColor {
|
||||
MGLLogDebug(@"Setting puckShadowColor: %@", puckShadowColor);
|
||||
_puckShadowColor = puckShadowColor;
|
||||
}
|
||||
|
||||
- (void)setPuckShadowOpacity:(CGFloat)puckShadowOpacity {
|
||||
MGLLogDebug(@"Setting puckShadowOpacity: %.2f", puckShadowOpacity);
|
||||
_puckShadowOpacity = puckShadowOpacity;
|
||||
}
|
||||
|
||||
- (void)setPuckArrowFillColor:(UIColor *)puckArrowFillColor {
|
||||
MGLLogDebug(@"Setting puckArrowFillColor: %@", puckArrowFillColor);
|
||||
_puckArrowFillColor = puckArrowFillColor;
|
||||
}
|
||||
|
||||
- (void)setHaloFillColor:(UIColor *)haloFillColor {
|
||||
MGLLogDebug(@"Setting haloFillColor: %@", haloFillColor);
|
||||
_haloFillColor = haloFillColor;
|
||||
}
|
||||
|
||||
- (void)setApproximateHaloFillColor:(UIColor *)approximateHaloFillColor {
|
||||
MGLLogDebug(@"Setting approximateHaloFillColor: %@", approximateHaloFillColor);
|
||||
_approximateHaloFillColor = approximateHaloFillColor;
|
||||
}
|
||||
|
||||
- (void)setApproximateHaloBorderColor:(UIColor *)approximateHaloBorderColor {
|
||||
MGLLogDebug(@"Setting approximateHaloBorderColor: %@", approximateHaloBorderColor);
|
||||
_approximateHaloBorderColor = approximateHaloBorderColor;
|
||||
}
|
||||
|
||||
- (void)setApproximateHaloBorderWidth:(CGFloat)approximateHaloBorderWidth {
|
||||
MGLLogDebug(@"Setting approximateHaloBorderWidth: %.2f", approximateHaloBorderWidth);
|
||||
_approximateHaloBorderWidth = approximateHaloBorderWidth;
|
||||
}
|
||||
|
||||
- (void)setApproximateHaloOpacity:(CGFloat)approximateHaloOpacity {
|
||||
MGLLogDebug(@"Setting approximateHaloOpacity: %.2f", approximateHaloOpacity);
|
||||
_approximateHaloOpacity = approximateHaloOpacity;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,5 +1,4 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLFoundation.h"
|
||||
|
||||
/// Project version number for Mapbox.
|
||||
@@ -8,69 +7,73 @@ FOUNDATION_EXPORT MGL_EXPORT double MapboxVersionNumber;
|
||||
/// Project version string for Mapbox.
|
||||
FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
|
||||
|
||||
#import "MGLAnnotationView.h"
|
||||
#import "MGLAccountManager.h"
|
||||
#import "MGLAnnotation.h"
|
||||
#import "MGLAnnotationImage.h"
|
||||
#import "MGLAnnotationView.h"
|
||||
#import "MGLAttributedExpression.h"
|
||||
#import "MGLAttributionInfo.h"
|
||||
#import "MGLBackgroundStyleLayer.h"
|
||||
#import "MGLCalloutView.h"
|
||||
#import "MGLCircleStyleLayer.h"
|
||||
#import "MGLClockDirectionFormatter.h"
|
||||
#import "MGLCluster.h"
|
||||
#import "MGLCompassButton.h"
|
||||
#import "MGLCompassDirectionFormatter.h"
|
||||
#import "MGLComputedShapeSource.h"
|
||||
#import "MGLCoordinateFormatter.h"
|
||||
#import "MGLDistanceFormatter.h"
|
||||
#import "MGLEvent.h"
|
||||
#import "MGLFeature.h"
|
||||
#import "MGLFillExtrusionStyleLayer.h"
|
||||
#import "MGLFillStyleLayer.h"
|
||||
#import "MGLForegroundStyleLayer.h"
|
||||
#import "MGLGeometry.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
#import "MGLHillshadeStyleLayer.h"
|
||||
#import "MGLImageSource.h"
|
||||
#import "MGLLight.h"
|
||||
#import "MGLLineStyleLayer.h"
|
||||
#import "MGLLocationManager.h"
|
||||
#import "MGLLoggingConfiguration.h"
|
||||
#import "MGLMapCamera.h"
|
||||
#import "MGLMapSnapshotter.h"
|
||||
#import "MGLMapView.h"
|
||||
#import "MGLMapView+IBAdditions.h"
|
||||
#import "MGLMapViewDelegate.h"
|
||||
#import "MGLMapView+IBAdditions.h"
|
||||
#import "MGLMultiPoint.h"
|
||||
#import "MGLNetworkConfiguration.h"
|
||||
#import "MGLObserver.h"
|
||||
#import "MGLOfflinePack.h"
|
||||
#import "MGLOfflineRegion.h"
|
||||
#import "MGLOfflineStorage.h"
|
||||
#import "MGLOpenGLStyleLayer.h"
|
||||
#import "MGLOverlay.h"
|
||||
#import "MGLPointAnnotation.h"
|
||||
#import "MGLPointCollection.h"
|
||||
#import "MGLPolygon.h"
|
||||
#import "MGLPolyline.h"
|
||||
#import "MGLRasterDEMSource.h"
|
||||
#import "MGLRasterStyleLayer.h"
|
||||
#import "MGLRasterTileSource.h"
|
||||
#import "MGLSDKMetricsManager.h"
|
||||
#import "MGLShape.h"
|
||||
#import "MGLShapeCollection.h"
|
||||
#import "MGLShapeOfflineRegion.h"
|
||||
#import "MGLShapeSource.h"
|
||||
#import "MGLSource.h"
|
||||
#import "MGLStyle.h"
|
||||
#import "MGLStyleLayer.h"
|
||||
#import "MGLForegroundStyleLayer.h"
|
||||
#import "MGLVectorStyleLayer.h"
|
||||
#import "MGLFillExtrusionStyleLayer.h"
|
||||
#import "MGLFillStyleLayer.h"
|
||||
#import "MGLLineStyleLayer.h"
|
||||
#import "MGLStyleValue.h"
|
||||
#import "MGLSymbolStyleLayer.h"
|
||||
#import "MGLRasterStyleLayer.h"
|
||||
#import "MGLCircleStyleLayer.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
#import "MGLHillshadeStyleLayer.h"
|
||||
#import "MGLBackgroundStyleLayer.h"
|
||||
#import "MGLOpenGLStyleLayer.h"
|
||||
#import "MGLSource.h"
|
||||
#import "MGLTileSource.h"
|
||||
#import "MGLVectorTileSource.h"
|
||||
#import "MGLShapeSource.h"
|
||||
#import "MGLComputedShapeSource.h"
|
||||
#import "MGLRasterTileSource.h"
|
||||
#import "MGLRasterDEMSource.h"
|
||||
#import "MGLImageSource.h"
|
||||
#import "MGLShapeOfflineRegion.h"
|
||||
#import "MGLTilePyramidOfflineRegion.h"
|
||||
#import "MGLTileSource.h"
|
||||
#import "MGLTypes.h"
|
||||
#import "MGLUserLocation.h"
|
||||
#import "MGLUserLocationAnnotationView.h"
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
#import "MGLStyleValue.h"
|
||||
#import "MGLAttributionInfo.h"
|
||||
#import "MGLMapSnapshotter.h"
|
||||
#import "MGLVectorStyleLayer.h"
|
||||
#import "MGLVectorTileSource.h"
|
||||
#import "NSExpression+MGLAdditions.h"
|
||||
#import "NSPredicate+MGLAdditions.h"
|
||||
#import "MGLLocationManager.h"
|
||||
#import "MGLLoggingConfiguration.h"
|
||||
#import "MGLNetworkConfiguration.h"
|
||||
#import "MGLAttributedExpression.h"
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
#import "MGLUserLocationAnnotationViewStyle.h"
|
||||
@@ -100,4 +100,8 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
|
||||
func mapView(_ mapView: MGLMapView, didFailToLoadImage imageName: String) -> UIImage? { return nil }
|
||||
|
||||
func mapView(_ mapView: MGLMapView, shouldRemoveStyleImage imageName: String) -> Bool { return false }
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didChangeLocationManagerAuthorization manager: MGLLocationManager) {}
|
||||
|
||||
func mapView(styleForDefaultUserLocationAnnotationView mapView: MGLMapView) -> MGLUserLocationAnnotationViewStyle { return MGLUserLocationAnnotationViewStyle() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user