committed by
Minh Nguyễn
parent
a65730803e
commit
77657b3896
@@ -44,6 +44,12 @@
|
||||
'../platform/darwin/src/MGLPolyline.mm',
|
||||
'../platform/darwin/src/MGLPolygon.mm',
|
||||
'../platform/darwin/src/MGLMapCamera.mm',
|
||||
'../platform/darwin/src/MGLDownloadable.mm',
|
||||
'../platform/darwin/src/MGLDownloadable_Private.h',
|
||||
'../platform/darwin/src/MGLDownloadController.mm',
|
||||
'../platform/darwin/src/MGLDownloadController_Private.h',
|
||||
'../platform/darwin/src/MGLDownloadRegion_Private.h',
|
||||
'../platform/darwin/src/MGLTilePyramidDownloadRegion.mm',
|
||||
'../platform/ios/src/MGLMapboxEvents.h',
|
||||
'../platform/ios/src/MGLMapboxEvents.m',
|
||||
'../platform/ios/src/MGLAPIClient.h',
|
||||
@@ -59,7 +65,6 @@
|
||||
'../platform/ios/src/MGLUserLocationAnnotationView.m',
|
||||
'../platform/ios/src/MGLAnnotationImage_Private.h',
|
||||
'../platform/ios/src/MGLAnnotationImage.m',
|
||||
'../platform/ios/include/MGLCalloutView.h',
|
||||
'../platform/ios/src/MGLCompactCalloutView.h',
|
||||
'../platform/ios/src/MGLCompactCalloutView.m',
|
||||
'../platform/ios/src/NSBundle+MGLAdditions.h',
|
||||
|
||||
30
platform/darwin/include/MGLDownloadController.h
Normal file
30
platform/darwin/include/MGLDownloadController.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLTypes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class MGLDownloadable;
|
||||
@protocol MGLDownloadRegion;
|
||||
|
||||
typedef void (^MGLDownloadableRegistrationCompletionHandler)(MGLDownloadable *downloadable, NSError *error);
|
||||
typedef void (^MGLDownloadableRemovalCompletionHandler)(NSError *error);
|
||||
typedef void (^MGLDownloadablesRequestCompletionHandler)(NS_ARRAY_OF(MGLDownloadable *) *downloadables, NSError *error);
|
||||
|
||||
@interface MGLDownloadController : NSObject
|
||||
|
||||
+ (instancetype)sharedController;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (void)addDownloadableForRegion:(id <MGLDownloadRegion>)downloadRegion withContext:(NSData *)context completionHandler:(MGLDownloadableRegistrationCompletionHandler)completion;
|
||||
|
||||
- (void)removeDownloadable:(MGLDownloadable *)downloadable withCompletionHandler:(MGLDownloadableRemovalCompletionHandler)completion;
|
||||
|
||||
- (void)requestDownloadablesWithCompletionHandler:(MGLDownloadablesRequestCompletionHandler)completion;
|
||||
|
||||
- (void)setMaximumAllowedMapboxTiles:(uint64_t)maximumCount;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
13
platform/darwin/include/MGLDownloadRegion.h
Normal file
13
platform/darwin/include/MGLDownloadRegion.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLTypes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLDownloadRegion <NSObject>
|
||||
|
||||
@property (nonatomic, readonly) NSURL *styleURL;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
49
platform/darwin/include/MGLDownloadable.h
Normal file
49
platform/darwin/include/MGLDownloadable.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLDownloadRegion.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLDownloadableDelegate;
|
||||
|
||||
typedef NS_ENUM (NSInteger, MGLDownloadableState) {
|
||||
MGLDownloadableStateInactive = 0,
|
||||
MGLDownloadableStateActive = 1,
|
||||
MGLDownloadableStateComplete = 2,
|
||||
};
|
||||
|
||||
typedef struct MGLDownloadableProgress {
|
||||
uint64_t countOfResourcesCompleted;
|
||||
uint64_t countOfBytesCompleted;
|
||||
uint64_t countOfResourcesExpected;
|
||||
uint64_t maximumResourcesExpected;
|
||||
} MGLDownloadableProgress;
|
||||
|
||||
@interface MGLDownloadable : NSObject
|
||||
|
||||
@property (nonatomic, readonly) id <MGLDownloadRegion> region;
|
||||
@property (nonatomic, readonly) NSData *context;
|
||||
@property (nonatomic, readonly) MGLDownloadableState state;
|
||||
@property (nonatomic, readonly) MGLDownloadableProgress progress;
|
||||
@property (nonatomic, weak, nullable) id <MGLDownloadableDelegate> delegate;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (void)resume;
|
||||
- (void)suspend;
|
||||
|
||||
- (void)requestProgress;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MGLDownloadableDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
- (void)downloadable:(MGLDownloadable *)downloadable progressDidChange:(MGLDownloadableProgress)progress;
|
||||
- (void)downloadable:(MGLDownloadable *)downloadable didReceiveError:(NSError *)error;
|
||||
- (void)downloadable:(MGLDownloadable *)downloadable didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
19
platform/darwin/include/MGLTilePyramidDownloadRegion.h
Normal file
19
platform/darwin/include/MGLTilePyramidDownloadRegion.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLDownloadRegion.h"
|
||||
#import "MGLGeometry.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MGLTilePyramidDownloadRegion : NSObject <MGLDownloadRegion>
|
||||
|
||||
@property (nonatomic, readonly) MGLCoordinateBounds bounds;
|
||||
@property (nonatomic, readonly) double minimumZoomLevel;
|
||||
@property (nonatomic, readonly) double maximumZoomLevel;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithStyleURL:(nullable NSURL *)styleURL bounds:(MGLCoordinateBounds)bounds fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -15,6 +15,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** Indicates an error occurred in the Mapbox SDK. */
|
||||
extern NSString * const MGLErrorDomain;
|
||||
|
||||
typedef NS_ENUM(NSInteger, MGLErrorCode) {
|
||||
MGLErrorCodeUnknown = -1,
|
||||
MGLErrorCodeNotFound = 1,
|
||||
MGLErrorCodeBadServerResponse = 2,
|
||||
MGLErrorCodeConnectionFailed = 3,
|
||||
};
|
||||
|
||||
/** The mode used to track the user location on the map. */
|
||||
typedef NS_ENUM(NSUInteger, MGLUserTrackingMode) {
|
||||
/** The map does not follow the user location. */
|
||||
|
||||
134
platform/darwin/src/MGLDownloadController.mm
Normal file
134
platform/darwin/src/MGLDownloadController.mm
Normal file
@@ -0,0 +1,134 @@
|
||||
#import "MGLDownloadController_Private.h"
|
||||
|
||||
#import "MGLAccountManager_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "MGLDownloadable_Private.h"
|
||||
#import "MGLDownloadRegion_Private.h"
|
||||
#import "MGLTilePyramidDownloadRegion.h"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
@interface MGLDownloadController ()
|
||||
|
||||
@property (nonatomic) mbgl::DefaultFileSource *mbglFileSource;
|
||||
|
||||
- (instancetype)initWithFileName:(NSString *)fileName NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLDownloadController
|
||||
|
||||
+ (instancetype)sharedController {
|
||||
static dispatch_once_t onceToken;
|
||||
static MGLDownloadController *sharedController;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedController = [[self alloc] initWithFileName:@"offline.db"];
|
||||
});
|
||||
return sharedController;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFileName:(NSString *)fileName {
|
||||
if (self = [super init]) {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:fileName];
|
||||
_mbglFileSource = new mbgl::DefaultFileSource(fileCachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);
|
||||
|
||||
// Observe for changes to the global access token (and find out the current one).
|
||||
[[MGLAccountManager sharedManager] addObserver:self
|
||||
forKeyPath:@"accessToken"
|
||||
options:(NSKeyValueObservingOptionInitial |
|
||||
NSKeyValueObservingOptionNew)
|
||||
context:NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];
|
||||
|
||||
delete _mbglFileSource;
|
||||
_mbglFileSource = nullptr;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NS_DICTIONARY_OF(NSString *, id) *)change context:(__unused void *)context {
|
||||
// Synchronize the file source’s access token with the global one in MGLAccountManager.
|
||||
if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) {
|
||||
NSString *accessToken = change[NSKeyValueChangeNewKey];
|
||||
if (![accessToken isKindOfClass:[NSNull class]]) {
|
||||
self.mbglFileSource->setAccessToken(accessToken.UTF8String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addDownloadableForRegion:(id <MGLDownloadRegion>)downloadRegion withContext:(NSData *)context completionHandler:(MGLDownloadableRegistrationCompletionHandler)completion {
|
||||
if (![downloadRegion conformsToProtocol:@protocol(MGLDownloadRegion_Private)]) {
|
||||
[NSException raise:@"Unsupported region type" format:
|
||||
@"Regions of type %@ are unsupported.", NSStringFromClass([downloadRegion class])];
|
||||
return;
|
||||
}
|
||||
|
||||
const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLDownloadRegion_Private>)downloadRegion offlineRegionDefinition];
|
||||
mbgl::OfflineRegionMetadata metadata(context.length);
|
||||
[context getBytes:&metadata[0] length:metadata.size()];
|
||||
self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegion> region) {
|
||||
NSError *error;
|
||||
if (exception) {
|
||||
NSString *errorDescription = @(mbgl::util::toString(exception).c_str());
|
||||
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:errorDescription ? @{
|
||||
NSLocalizedDescriptionKey: errorDescription,
|
||||
} : nil];
|
||||
}
|
||||
if (completion) {
|
||||
MGLDownloadable *downloadable = [[MGLDownloadable alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(*region))];
|
||||
dispatch_async(dispatch_get_main_queue(), [&, completion, error, downloadable](void) {
|
||||
completion(downloadable, error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeDownloadable:(MGLDownloadable *)downloadable withCompletionHandler:(MGLDownloadableRemovalCompletionHandler)completion {
|
||||
self.mbglFileSource->deleteOfflineRegion(std::move(*downloadable.mbglOfflineRegion), [&, completion](std::exception_ptr exception) {
|
||||
NSError *error;
|
||||
if (exception) {
|
||||
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
|
||||
NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
|
||||
}];
|
||||
}
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), [&, completion, error](void) {
|
||||
completion(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)requestDownloadablesWithCompletionHandler:(MGLDownloadablesRequestCompletionHandler)completion {
|
||||
self.mbglFileSource->listOfflineRegions([&, completion](std::exception_ptr exception, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) {
|
||||
NSError *error;
|
||||
if (exception) {
|
||||
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
|
||||
NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
|
||||
}];
|
||||
}
|
||||
NSMutableArray *downloadables;
|
||||
if (regions) {
|
||||
downloadables = [NSMutableArray arrayWithCapacity:regions->size()];
|
||||
for (mbgl::OfflineRegion ®ion : *regions) {
|
||||
MGLDownloadable *downloadable = [[MGLDownloadable alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))];
|
||||
[downloadables addObject:downloadable];
|
||||
}
|
||||
}
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), [&, completion, error, downloadables](void) {
|
||||
completion(downloadables, error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setMaximumAllowedMapboxTiles:(uint64_t)maximumCount {
|
||||
_mbglFileSource->setOfflineMapboxTileCountLimit(maximumCount);
|
||||
}
|
||||
|
||||
@end
|
||||
15
platform/darwin/src/MGLDownloadController_Private.h
Normal file
15
platform/darwin/src/MGLDownloadController_Private.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#import "MGLDownloadController.h"
|
||||
|
||||
#import "MGLDownloadable.h"
|
||||
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MGLDownloadController (Private)
|
||||
|
||||
@property (nonatomic) mbgl::DefaultFileSource *mbglFileSource;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
17
platform/darwin/src/MGLDownloadRegion_Private.h
Normal file
17
platform/darwin/src/MGLDownloadRegion_Private.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLDownloadRegion.h"
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLDownloadRegion_Private <MGLDownloadRegion>
|
||||
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition;
|
||||
|
||||
- (const mbgl::OfflineRegionDefinition)offlineRegionDefinition;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
160
platform/darwin/src/MGLDownloadable.mm
Normal file
160
platform/darwin/src/MGLDownloadable.mm
Normal file
@@ -0,0 +1,160 @@
|
||||
#import "MGLDownloadable_Private.h"
|
||||
|
||||
#import "MGLDownloadController_Private.h"
|
||||
#import "MGLDownloadRegion_Private.h"
|
||||
#import "MGLTilePyramidDownloadRegion.h"
|
||||
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
class MBGLOfflineRegionObserver;
|
||||
|
||||
@interface MGLDownloadable ()
|
||||
|
||||
@property (nonatomic, readwrite) mbgl::OfflineRegion *mbglOfflineRegion;
|
||||
@property (nonatomic, readwrite) MBGLOfflineRegionObserver *mbglOfflineRegionObserver;
|
||||
@property (nonatomic, readwrite) MGLDownloadableState state;
|
||||
@property (nonatomic, readwrite) MGLDownloadableProgress progress;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLDownloadable
|
||||
|
||||
- (instancetype)init {
|
||||
[NSException raise:@"Method unavailable"
|
||||
format:
|
||||
@"-[MGLDownloadable init] is unavailable. "
|
||||
@"Use +[MGLDownloadController addDownloadRegion:context:completionHandler:] instead."];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region {
|
||||
if (self = [super init]) {
|
||||
_mbglOfflineRegion = region;
|
||||
_state = MGLDownloadableStateInactive;
|
||||
_mbglOfflineRegionObserver = new MBGLOfflineRegionObserver(self);
|
||||
|
||||
mbgl::DefaultFileSource *mbglFileSource = [[MGLDownloadController sharedController] mbglFileSource];
|
||||
mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(*_mbglOfflineRegionObserver));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
delete _mbglOfflineRegionObserver;
|
||||
_mbglOfflineRegionObserver = nullptr;
|
||||
}
|
||||
|
||||
- (id <MGLDownloadRegion>)region {
|
||||
const mbgl::OfflineRegionDefinition ®ionDefinition = _mbglOfflineRegion->getDefinition();
|
||||
NSAssert([MGLTilePyramidDownloadRegion conformsToProtocol:@protocol(MGLDownloadRegion_Private)], @"MGLTilePyramidDownloadRegion should conform to MGLDownloadRegion_Private.");
|
||||
return [(id <MGLDownloadRegion_Private>)[MGLTilePyramidDownloadRegion alloc] initWithOfflineRegionDefinition:regionDefinition];
|
||||
}
|
||||
|
||||
- (NSData *)context {
|
||||
const mbgl::OfflineRegionMetadata &metadata = _mbglOfflineRegion->getMetadata();
|
||||
return [NSData dataWithBytes:&metadata[0] length:metadata.size()];
|
||||
}
|
||||
|
||||
- (void)resume {
|
||||
mbgl::DefaultFileSource *mbglFileSource = [[MGLDownloadController sharedController] mbglFileSource];
|
||||
mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active);
|
||||
self.state = MGLDownloadableStateActive;
|
||||
}
|
||||
|
||||
- (void)suspend {
|
||||
mbgl::DefaultFileSource *mbglFileSource = [[MGLDownloadController sharedController] mbglFileSource];
|
||||
mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive);
|
||||
self.state = MGLDownloadableStateInactive;
|
||||
}
|
||||
|
||||
- (void)requestProgress {
|
||||
mbgl::DefaultFileSource *mbglFileSource = [[MGLDownloadController sharedController] mbglFileSource];
|
||||
|
||||
__weak MGLDownloadable *weakSelf = self;
|
||||
mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](__unused std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegionStatus> status) {
|
||||
if (status) {
|
||||
mbgl::OfflineRegionStatus checkedStatus = *status;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
MGLDownloadable *strongSelf = weakSelf;
|
||||
[strongSelf offlineRegionStatusDidChange:checkedStatus];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)offlineRegionStatusDidChange:(mbgl::OfflineRegionStatus)status {
|
||||
switch (status.downloadState) {
|
||||
case mbgl::OfflineRegionDownloadState::Inactive:
|
||||
self.state = status.complete() ? MGLDownloadableStateComplete : MGLDownloadableStateInactive;
|
||||
break;
|
||||
|
||||
case mbgl::OfflineRegionDownloadState::Active:
|
||||
self.state = MGLDownloadableStateActive;
|
||||
break;
|
||||
}
|
||||
|
||||
MGLDownloadableProgress progress;
|
||||
progress.countOfResourcesCompleted = status.completedResourceCount;
|
||||
progress.countOfBytesCompleted = status.completedResourceSize;
|
||||
progress.countOfResourcesExpected = status.requiredResourceCount;
|
||||
progress.maximumResourcesExpected = status.requiredResourceCountIsPrecise ? status.requiredResourceCount : UINT64_MAX;
|
||||
self.progress = progress;
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(downloadable:progressDidChange:)]) {
|
||||
[self.delegate downloadable:self progressDidChange:progress];
|
||||
}
|
||||
}
|
||||
|
||||
NSError *MGLErrorFromResponseError(mbgl::Response::Error error) {
|
||||
NSInteger errorCode = MGLErrorCodeUnknown;
|
||||
switch (error.reason) {
|
||||
case mbgl::Response::Error::Reason::NotFound:
|
||||
errorCode = MGLErrorCodeNotFound;
|
||||
break;
|
||||
|
||||
case mbgl::Response::Error::Reason::Server:
|
||||
errorCode = MGLErrorCodeBadServerResponse;
|
||||
break;
|
||||
|
||||
case mbgl::Response::Error::Reason::Connection:
|
||||
errorCode = MGLErrorCodeConnectionFailed;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return [NSError errorWithDomain:MGLErrorDomain code:errorCode userInfo:@{
|
||||
NSLocalizedFailureReasonErrorKey: @(error.message.c_str())
|
||||
}];
|
||||
}
|
||||
|
||||
void MBGLOfflineRegionObserver::statusChanged(mbgl::OfflineRegionStatus status) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSCAssert(downloadable, @"MBGLOfflineRegionObserver is dangling without an associated MGLDownloadable.");
|
||||
|
||||
[downloadable offlineRegionStatusDidChange:status];
|
||||
});
|
||||
}
|
||||
|
||||
void MBGLOfflineRegionObserver::responseError(mbgl::Response::Error error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSCAssert(downloadable, @"MBGLOfflineRegionObserver is dangling without an associated MGLDownloadable.");
|
||||
|
||||
if ([downloadable.delegate respondsToSelector:@selector(downloadable:didReceiveError:)]) {
|
||||
[downloadable.delegate downloadable:downloadable didReceiveError:MGLErrorFromResponseError(error)];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MBGLOfflineRegionObserver::mapboxTileCountLimitExceeded(uint64_t limit) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSCAssert(downloadable, @"MBGLOfflineRegionObserver is dangling without an associated MGLDownloadable.");
|
||||
|
||||
if ([downloadable.delegate respondsToSelector:@selector(downloadable:didReceiveMaximumAllowedMapboxTiles:)]) {
|
||||
[downloadable.delegate downloadable:downloadable didReceiveMaximumAllowedMapboxTiles:limit];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
26
platform/darwin/src/MGLDownloadable_Private.h
Normal file
26
platform/darwin/src/MGLDownloadable_Private.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#import "MGLDownloadable.h"
|
||||
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
|
||||
class MBGLOfflineRegionObserver;
|
||||
|
||||
@interface MGLDownloadable (Private)
|
||||
|
||||
@property (nonatomic) mbgl::OfflineRegion *mbglOfflineRegion;
|
||||
@property (nonatomic, readonly) MBGLOfflineRegionObserver *mbglOfflineRegionObserver;
|
||||
|
||||
- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region;
|
||||
|
||||
@end
|
||||
|
||||
class MBGLOfflineRegionObserver : public mbgl::OfflineRegionObserver {
|
||||
public:
|
||||
MBGLOfflineRegionObserver(MGLDownloadable *downloadable_) : downloadable(downloadable_) {}
|
||||
|
||||
void statusChanged(mbgl::OfflineRegionStatus status) override;
|
||||
void responseError(mbgl::Response::Error error) override;
|
||||
void mapboxTileCountLimitExceeded(uint64_t limit) override;
|
||||
|
||||
private:
|
||||
__weak MGLDownloadable *downloadable = nullptr;
|
||||
};
|
||||
62
platform/darwin/src/MGLTilePyramidDownloadRegion.mm
Normal file
62
platform/darwin/src/MGLTilePyramidDownloadRegion.mm
Normal file
@@ -0,0 +1,62 @@
|
||||
#import "MGLTilePyramidDownloadRegion.h"
|
||||
|
||||
#import "MGLDownloadRegion_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "MGLStyle.h"
|
||||
|
||||
@interface MGLTilePyramidDownloadRegion () <MGLDownloadRegion_Private>
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLTilePyramidDownloadRegion {
|
||||
NSURL *_styleURL;
|
||||
}
|
||||
|
||||
@synthesize styleURL = _styleURL;
|
||||
|
||||
- (instancetype)init {
|
||||
[NSException raise:@"Method unavailable"
|
||||
format:
|
||||
@"-[MGLTilePyramidDownloadRegion init] is unavailable. "
|
||||
@"Use -initWithStyleURL:bounds:fromZoomLevel:toZoomLevel: instead."];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStyleURL:(NSURL *)styleURL bounds:(MGLCoordinateBounds)bounds fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel {
|
||||
if (self = [super init]) {
|
||||
if (!styleURL) {
|
||||
styleURL = [MGLStyle streetsStyleURL];
|
||||
}
|
||||
|
||||
if (!styleURL.scheme) {
|
||||
// Assume a relative path into the application bundle.
|
||||
styleURL = [NSURL URLWithString:[@"asset://" stringByAppendingString:styleURL.absoluteString]];
|
||||
}
|
||||
|
||||
_styleURL = styleURL;
|
||||
_bounds = bounds;
|
||||
_minimumZoomLevel = minimumZoomLevel;
|
||||
_maximumZoomLevel = maximumZoomLevel;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition {
|
||||
NSURL *styleURL = [NSURL URLWithString:@(definition.styleURL.c_str())];
|
||||
MGLCoordinateBounds bounds = MGLCoordinateBoundsFromLatLngBounds(definition.bounds);
|
||||
return [self initWithStyleURL:styleURL bounds:bounds fromZoomLevel:definition.minZoom toZoomLevel:definition.maxZoom];
|
||||
}
|
||||
|
||||
- (const mbgl::OfflineRegionDefinition)offlineRegionDefinition {
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
|
||||
#elif TARGET_OS_MAC
|
||||
const float scaleFactor = [NSScreen mainScreen].backingScaleFactor;
|
||||
#endif
|
||||
return mbgl::OfflineTilePyramidRegionDefinition(_styleURL.absoluteString.UTF8String,
|
||||
MGLLatLngBoundsFromCoordinateBounds(_bounds),
|
||||
_minimumZoomLevel, _maximumZoomLevel,
|
||||
scaleFactor);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -12,6 +12,9 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "MGLCalloutView.h"
|
||||
#import "MGLMapCamera.h"
|
||||
#import "MGLGeometry.h"
|
||||
#import "MGLDownloadable.h"
|
||||
#import "MGLDownloadRegion.h"
|
||||
#import "MGLDownloadController.h"
|
||||
#import "MGLMapView.h"
|
||||
#import "MGLMapView+IBAdditions.h"
|
||||
#import "MGLMapView+MGLCustomStyleLayerAdditions.h"
|
||||
@@ -22,5 +25,6 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "MGLPolyline.h"
|
||||
#import "MGLShape.h"
|
||||
#import "MGLStyle.h"
|
||||
#import "MGLTilePyramidDownloadRegion.h"
|
||||
#import "MGLTypes.h"
|
||||
#import "MGLUserLocation.h"
|
||||
|
||||
@@ -17,6 +17,8 @@ static void InitializeMapbox() {
|
||||
|
||||
[MGLAccountManager class];
|
||||
[MGLAnnotationImage class];
|
||||
[MGLDownloadable class];
|
||||
[MGLDownloadController class];
|
||||
[MGLMapCamera class];
|
||||
[MGLMapView class];
|
||||
[MGLMultiPoint class];
|
||||
@@ -25,5 +27,6 @@ static void InitializeMapbox() {
|
||||
[MGLPolyline class];
|
||||
[MGLShape class];
|
||||
[MGLStyle class];
|
||||
[MGLTilePyramidDownloadRegion class];
|
||||
[MGLUserLocation class];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user