react-native-maps 1.21.0-alpha.4 → 1.21.0-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/rnmaps/fabric/NativeAirMapsModule.java +51 -0
- package/android/src/main/java/com/rnmaps/maps/MapAirModulePackage.java +46 -0
- package/ios/AirGoogleMaps/AIRGoogleMap.h +8 -2
- package/ios/AirGoogleMaps/AIRGoogleMap.m +179 -11
- package/ios/AirGoogleMaps/AIRGoogleMapCircle.h +0 -1
- package/ios/AirGoogleMaps/AIRGoogleMapCircle.m +23 -11
- package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.h +13 -0
- package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.m +10 -0
- package/ios/AirGoogleMaps/AIRGoogleMapManager.h +7 -0
- package/ios/AirGoogleMaps/AIRGoogleMapManager.m +30 -119
- package/ios/AirGoogleMaps/AIRGoogleMapMarker.h +2 -0
- package/ios/AirGoogleMaps/AIRGoogleMapMarker.m +347 -243
- package/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +0 -1
- package/ios/AirGoogleMaps/AIRGoogleMapOverlay.h +0 -1
- package/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +5 -4
- package/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +32 -2
- package/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +3 -3
- package/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +3 -2
- package/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +2 -3
- package/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +2 -2
- package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.h +1 -1
- package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.m +2 -2
- package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h +3 -0
- package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +18 -0
- package/ios/AirGoogleMaps/RNMapsGoogleMapView.h +26 -0
- package/ios/AirGoogleMaps/RNMapsGoogleMapView.mm +599 -0
- package/ios/AirGoogleMaps/RNMapsGoogleMapViewManager.mm +25 -0
- package/ios/AirGoogleMaps/RNMapsGooglePolygonView.h +26 -0
- package/ios/AirGoogleMaps/RNMapsGooglePolygonView.mm +217 -0
- package/ios/AirGoogleMaps/RNMapsGooglePolygonViewManager.mm +25 -0
- package/ios/AirMaps/AIRMap.h +8 -5
- package/ios/AirMaps/AIRMap.m +284 -141
- package/ios/AirMaps/AIRMapManager.m +12 -21
- package/ios/AirMaps/AIRMapMarker.h +1 -0
- package/ios/AirMaps/AIRMapMarker.m +165 -103
- package/ios/AirMaps/Callout/SMCalloutView.m +1 -1
- package/ios/AirMaps/RCTConvert+AirMap.h +4 -0
- package/ios/AirMaps/RCTConvert+AirMap.m +2 -0
- package/ios/AirMaps/RNMapsAirModule.h +3 -0
- package/ios/AirMaps/RNMapsAirModule.mm +42 -172
- package/ios/AirMaps/RNMapsAirModuleDelegate.h +24 -0
- package/ios/AirMaps/RNMapsHostVewDelegate.h +17 -0
- package/ios/AirMaps/RNMapsMapView.h +6 -3
- package/ios/AirMaps/RNMapsMapView.mm +341 -334
- package/ios/AirMaps/RNMapsMarkerView.h +24 -0
- package/ios/AirMaps/RNMapsMarkerView.mm +422 -0
- package/ios/AirMaps/RNMapsMarkerViewManager.mm +21 -0
- package/ios/AirMaps/UIView +AirMap.m +20 -0
- package/ios/AirMaps/UIView+AirMap.h +11 -0
- package/lib/MapMarker.d.ts +15 -2
- package/lib/MapMarker.js +53 -9
- package/lib/MapMarkerNativeComponent.js +0 -2
- package/lib/MapOverlay.d.ts +1 -1
- package/lib/MapView.d.ts +5 -22
- package/lib/MapView.js +34 -21
- package/lib/{FabricMapView.d.ts → createFabricMap.d.ts} +7 -6
- package/lib/createFabricMap.js +175 -0
- package/lib/decorateMapComponent.js +18 -0
- package/lib/specs/NativeAirMapsModule.d.ts +2 -2
- package/lib/specs/NativeComponentGoogleMapView.d.ts +713 -0
- package/lib/specs/NativeComponentGoogleMapView.js +21 -0
- package/lib/specs/NativeComponentGooglePolygon.d.ts +75 -0
- package/lib/specs/NativeComponentGooglePolygon.js +9 -0
- package/lib/specs/NativeComponentMapView.d.ts +21 -45
- package/lib/specs/NativeComponentMarker.d.ts +258 -0
- package/lib/specs/NativeComponentMarker.js +21 -0
- package/package.json +7 -7
- package/react-native-maps.podspec +1 -1
- package/lib/FabricMapView.js +0 -175
package/ios/AirMaps/AIRMap.m
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#import "AIRMapWMSTile.h"
|
|
21
21
|
#import "AIRMapLocalTile.h"
|
|
22
22
|
#import "AIRMapOverlay.h"
|
|
23
|
+
#import "AIRMapSnapshot.h"
|
|
23
24
|
|
|
24
25
|
const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1;
|
|
25
26
|
const CGFloat AIRMapZoomBoundBuffer = 0.01;
|
|
@@ -38,8 +39,6 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
38
39
|
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
|
|
39
40
|
@property (nonatomic, assign) NSNumber *shouldZoomEnabled;
|
|
40
41
|
@property (nonatomic, assign) NSNumber *shouldScrollEnabled;
|
|
41
|
-
@property (nonatomic, strong) MKCompassButton *defaultCompassButton;
|
|
42
|
-
@property (nonatomic, strong) MKCompassButton *overlayCompassButton;
|
|
43
42
|
|
|
44
43
|
- (void)updateScrollEnabled;
|
|
45
44
|
- (void)updateZoomEnabled;
|
|
@@ -51,7 +50,9 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
51
50
|
UIView *_legalLabel;
|
|
52
51
|
BOOL _initialRegionSet;
|
|
53
52
|
BOOL _initialCameraSet;
|
|
54
|
-
|
|
53
|
+
BOOL _initialized;
|
|
54
|
+
BOOL _loadingStarted;
|
|
55
|
+
|
|
55
56
|
// Array to manually track RN subviews
|
|
56
57
|
//
|
|
57
58
|
// AIRMap implicitly creates subviews that aren't regular RN children
|
|
@@ -69,7 +70,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
69
70
|
if ((self = [super init])) {
|
|
70
71
|
_hasStartedRendering = NO;
|
|
71
72
|
_reactSubviews = [NSMutableArray new];
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
// Find Apple link label
|
|
74
75
|
for (UIView *subview in self.subviews) {
|
|
75
76
|
if ([NSStringFromClass(subview.class) isEqualToString:@"MKAttributionLabel"]) {
|
|
@@ -79,16 +80,18 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
79
80
|
break;
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
// 3rd-party callout view for MapKit that has more options than the built-in. It's painstakingly built to
|
|
84
85
|
// be identical to the built-in callout view (which has a private API)
|
|
85
86
|
self.calloutView = [SMCalloutView platformCalloutView];
|
|
86
87
|
self.calloutView.delegate = self;
|
|
87
|
-
|
|
88
|
-
self.
|
|
89
|
-
self.
|
|
88
|
+
|
|
89
|
+
self.minZoom = 0;
|
|
90
|
+
self.maxZoom = AIRMapMaxZoomLevel;
|
|
90
91
|
self.compassOffset = CGPointMake(0, 0);
|
|
91
92
|
self.legacyZoomConstraintsEnabled = YES;
|
|
93
|
+
_initialized = YES;
|
|
94
|
+
[self listenToMemoryWarnings];
|
|
92
95
|
}
|
|
93
96
|
return self;
|
|
94
97
|
}
|
|
@@ -199,6 +202,20 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
199
202
|
}
|
|
200
203
|
return marker;
|
|
201
204
|
}
|
|
205
|
+
// Create Polyline with coordinates
|
|
206
|
+
-(void) fitToCoordinates:(NSArray<AIRMapCoordinate*>*) coordinates edgePadding:(UIEdgeInsets) edgeInsets animated:(Boolean) animated {
|
|
207
|
+
CLLocationCoordinate2D coords[coordinates.count];
|
|
208
|
+
for(int i = 0; i < coordinates.count; i++)
|
|
209
|
+
{
|
|
210
|
+
coords[i] = coordinates[i].coordinate;
|
|
211
|
+
}
|
|
212
|
+
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
|
|
213
|
+
|
|
214
|
+
// Set Map viewport
|
|
215
|
+
|
|
216
|
+
[self setVisibleMapRect:[polyline boundingMapRect] edgePadding:edgeInsets animated:animated];
|
|
217
|
+
}
|
|
218
|
+
|
|
202
219
|
|
|
203
220
|
- (CGRect) frameForMarker:(AIRMapMarker*) mrkAnn {
|
|
204
221
|
MKAnnotationView* mrkView = [self viewForAnnotation: mrkAnn];
|
|
@@ -206,29 +223,6 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
206
223
|
return mrkFrame;
|
|
207
224
|
}
|
|
208
225
|
|
|
209
|
-
- (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible {
|
|
210
|
-
NSMutableDictionary* markersFrames = [NSMutableDictionary new];
|
|
211
|
-
for (AIRMapMarker* mrkAnn in self.markers) {
|
|
212
|
-
CGRect frame = [self frameForMarker:mrkAnn];
|
|
213
|
-
CGPoint point = [self convertCoordinate:mrkAnn.coordinate toPointToView:self];
|
|
214
|
-
NSDictionary* frameDict = @{
|
|
215
|
-
@"x": @(frame.origin.x),
|
|
216
|
-
@"y": @(frame.origin.y),
|
|
217
|
-
@"width": @(frame.size.width),
|
|
218
|
-
@"height": @(frame.size.height)
|
|
219
|
-
};
|
|
220
|
-
NSDictionary* pointDict = @{
|
|
221
|
-
@"x": @(point.x),
|
|
222
|
-
@"y": @(point.y)
|
|
223
|
-
};
|
|
224
|
-
NSString* k = mrkAnn.identifier;
|
|
225
|
-
BOOL isVisible = CGRectIntersectsRect(self.bounds, frame);
|
|
226
|
-
if (k != nil && (!onlyVisible || isVisible)) {
|
|
227
|
-
[markersFrames setObject:@{ @"frame": frameDict, @"point": pointDict } forKey:k];
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return markersFrames;
|
|
231
|
-
}
|
|
232
226
|
|
|
233
227
|
- (AIRMapMarker*) markerAtPoint:(CGPoint)point {
|
|
234
228
|
AIRMapMarker* mrk = nil;
|
|
@@ -257,16 +251,16 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
257
251
|
// Allow touches to be sent to our calloutview.
|
|
258
252
|
// See this for some discussion of why we need to override this: https://github.com/nfarina/calloutview/pull/9
|
|
259
253
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
|
260
|
-
|
|
254
|
+
|
|
261
255
|
CGPoint touchPoint = [self.calloutView convertPoint:point fromView:self];
|
|
262
256
|
UIView *touchedView = [self.calloutView hitTest:touchPoint withEvent:event];
|
|
263
|
-
|
|
257
|
+
|
|
264
258
|
if (touchedView) {
|
|
265
259
|
UIWindow* win = [[[UIApplication sharedApplication] windows] firstObject];
|
|
266
260
|
AIRMapCalloutSubview* calloutSubview = nil;
|
|
267
261
|
AIRMapCallout* callout = nil;
|
|
268
262
|
AIRMapMarker* marker = nil;
|
|
269
|
-
|
|
263
|
+
|
|
270
264
|
UIView* tmp = touchedView;
|
|
271
265
|
while (tmp && tmp != win && tmp != self.calloutView) {
|
|
272
266
|
if ([tmp respondsToSelector:@selector(onPress)]) {
|
|
@@ -278,7 +272,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
278
272
|
}
|
|
279
273
|
tmp = tmp.superview;
|
|
280
274
|
}
|
|
281
|
-
|
|
275
|
+
|
|
282
276
|
if (callout) {
|
|
283
277
|
marker = [self markerForCallout:callout];
|
|
284
278
|
if (marker) {
|
|
@@ -288,49 +282,49 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
288
282
|
}
|
|
289
283
|
}
|
|
290
284
|
}
|
|
291
|
-
|
|
285
|
+
|
|
292
286
|
return calloutSubview ? calloutSubview : touchedView;
|
|
293
287
|
}
|
|
294
|
-
|
|
288
|
+
|
|
295
289
|
return [super hitTest:point withEvent:event];
|
|
296
290
|
}
|
|
297
291
|
|
|
298
292
|
#pragma mark SMCalloutViewDelegate
|
|
299
293
|
|
|
300
294
|
- (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset {
|
|
301
|
-
|
|
295
|
+
|
|
302
296
|
// When the callout is being asked to present in a way where it or its target will be partially offscreen, it asks us
|
|
303
297
|
// if we'd like to reposition our surface first so the callout is completely visible. Here we scroll the map into view,
|
|
304
298
|
// but it takes some math because we have to deal in lon/lat instead of the given offset in pixels.
|
|
305
|
-
|
|
299
|
+
|
|
306
300
|
CLLocationCoordinate2D coordinate = self.region.center;
|
|
307
|
-
|
|
301
|
+
|
|
308
302
|
// where's the center coordinate in terms of our view?
|
|
309
303
|
CGPoint center = [self convertCoordinate:coordinate toPointToView:self];
|
|
310
|
-
|
|
304
|
+
|
|
311
305
|
// move it by the requested offset
|
|
312
306
|
center.x -= offset.width;
|
|
313
307
|
center.y -= offset.height;
|
|
314
|
-
|
|
308
|
+
|
|
315
309
|
// and translate it back into map coordinates
|
|
316
310
|
coordinate = [self convertPoint:center toCoordinateFromView:self];
|
|
317
|
-
|
|
311
|
+
|
|
318
312
|
// move the map!
|
|
319
313
|
[self setCenterCoordinate:coordinate animated:YES];
|
|
320
|
-
|
|
314
|
+
|
|
321
315
|
// tell the callout to wait for a while while we scroll (we assume the scroll delay for MKMapView matches UIScrollView)
|
|
322
316
|
return kSMCalloutViewRepositionDelayForUIScrollView;
|
|
323
317
|
}
|
|
324
318
|
|
|
325
|
-
#pragma mark
|
|
319
|
+
#pragma mark RNMapsAirModuleDelegate.h
|
|
326
320
|
|
|
327
321
|
- (NSArray *)getMapBoundaries
|
|
328
322
|
{
|
|
329
323
|
MKMapRect mapRect = self.visibleMapRect;
|
|
330
|
-
|
|
324
|
+
|
|
331
325
|
CLLocationCoordinate2D northEast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(mapRect), mapRect.origin.y));
|
|
332
326
|
CLLocationCoordinate2D southWest = MKCoordinateForMapPoint(MKMapPointMake(mapRect.origin.x, MKMapRectGetMaxY(mapRect)));
|
|
333
|
-
|
|
327
|
+
|
|
334
328
|
return @[
|
|
335
329
|
@[
|
|
336
330
|
[NSNumber numberWithDouble:northEast.longitude],
|
|
@@ -342,6 +336,174 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
342
336
|
]
|
|
343
337
|
];
|
|
344
338
|
}
|
|
339
|
+
- (NSDictionary *) getPointForCoordinates:(CLLocationCoordinate2D) location
|
|
340
|
+
{
|
|
341
|
+
CGPoint touchPoint = [self convertCoordinate:location toPointToView:self];
|
|
342
|
+
|
|
343
|
+
return @{
|
|
344
|
+
@"x": @(touchPoint.x),
|
|
345
|
+
@"y": @(touchPoint.y),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
- (NSDictionary *) getCoordinatesForPoint:(CGPoint)point
|
|
349
|
+
{
|
|
350
|
+
CLLocationCoordinate2D coordinate = [self convertPoint:point toCoordinateFromView:self];
|
|
351
|
+
return @{
|
|
352
|
+
@"latitude": @(coordinate.latitude),
|
|
353
|
+
@"longitude": @(coordinate.longitude),
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
- (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible {
|
|
359
|
+
NSMutableDictionary* markersFrames = [NSMutableDictionary new];
|
|
360
|
+
for (AIRMapMarker* mrkAnn in self.markers) {
|
|
361
|
+
CGRect frame = [self frameForMarker:mrkAnn];
|
|
362
|
+
CGPoint point = [self convertCoordinate:mrkAnn.coordinate toPointToView:self];
|
|
363
|
+
NSDictionary* frameDict = @{
|
|
364
|
+
@"x": @(frame.origin.x),
|
|
365
|
+
@"y": @(frame.origin.y),
|
|
366
|
+
@"width": @(frame.size.width),
|
|
367
|
+
@"height": @(frame.size.height)
|
|
368
|
+
};
|
|
369
|
+
NSDictionary* pointDict = @{
|
|
370
|
+
@"x": @(point.x),
|
|
371
|
+
@"y": @(point.y)
|
|
372
|
+
};
|
|
373
|
+
NSString* k = mrkAnn.identifier;
|
|
374
|
+
BOOL isVisible = CGRectIntersectsRect(self.bounds, frame);
|
|
375
|
+
if (k != nil && (!onlyVisible || isVisible)) {
|
|
376
|
+
[markersFrames setObject:@{ @"frame": frameDict, @"point": pointDict } forKey:k];
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return markersFrames;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
- (NSDictionary *) getCameraDic {
|
|
383
|
+
MKMapCamera *camera = [self camera];
|
|
384
|
+
return @{
|
|
385
|
+
@"center": @{
|
|
386
|
+
@"latitude": @(camera.centerCoordinate.latitude),
|
|
387
|
+
@"longitude": @(camera.centerCoordinate.longitude),
|
|
388
|
+
},
|
|
389
|
+
@"pitch": @(camera.pitch),
|
|
390
|
+
@"heading": @(camera.heading),
|
|
391
|
+
@"altitude": @(camera.altitude),
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
- (void)takeSnapshotWithConfig:(NSDictionary *)config
|
|
395
|
+
success:(RCTPromiseResolveBlock)success error:(RCTPromiseRejectBlock)error
|
|
396
|
+
{
|
|
397
|
+
|
|
398
|
+
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
|
|
399
|
+
|
|
400
|
+
options.mapType = self.mapType;
|
|
401
|
+
NSNumber *width = config[@"width"];
|
|
402
|
+
NSNumber *height = config[@"height"];
|
|
403
|
+
NSNumber *quality = config[@"quality"];
|
|
404
|
+
NSString*format =config[@"format"];
|
|
405
|
+
NSString*result =config[@"result"];
|
|
406
|
+
if (config[@"region"]){
|
|
407
|
+
MKCoordinateRegion region = [RCTConvert MKCoordinateRegion:config[@"region"]];
|
|
408
|
+
options.region = region;
|
|
409
|
+
} else
|
|
410
|
+
{
|
|
411
|
+
options.region = self.region;
|
|
412
|
+
}
|
|
413
|
+
options.size = CGSizeMake(
|
|
414
|
+
([width floatValue] == 0) ? self.bounds.size.width : [width floatValue],
|
|
415
|
+
([height floatValue] == 0) ? self.bounds.size.height : [height floatValue]
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
options.scale = [[UIScreen mainScreen] scale];
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
|
|
422
|
+
|
|
423
|
+
[self takeMapSnapshot:snapshotter
|
|
424
|
+
format:format
|
|
425
|
+
quality:[quality floatValue]
|
|
426
|
+
result:result
|
|
427
|
+
success:success error:error];
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
#pragma mark Take Snapshot
|
|
431
|
+
- (void)takeMapSnapshot:(MKMapSnapshotter *) snapshotter
|
|
432
|
+
format:(NSString *)format
|
|
433
|
+
quality:(CGFloat) quality
|
|
434
|
+
result:(NSString *)result
|
|
435
|
+
success:(RCTPromiseResolveBlock) success
|
|
436
|
+
error:(RCTPromiseRejectBlock) errorCallback {
|
|
437
|
+
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
|
|
438
|
+
NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
|
|
439
|
+
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
|
|
440
|
+
|
|
441
|
+
[snapshotter startWithQueue:dispatch_get_main_queue()
|
|
442
|
+
completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
|
|
443
|
+
if (error) {
|
|
444
|
+
errorCallback(@"snapshotterError", @"failed", error);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:nil];
|
|
448
|
+
|
|
449
|
+
UIImage *image = snapshot.image;
|
|
450
|
+
UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
|
|
451
|
+
{
|
|
452
|
+
[image drawAtPoint:CGPointMake(0.0f, 0.0f)];
|
|
453
|
+
|
|
454
|
+
CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
|
|
455
|
+
|
|
456
|
+
for (id <AIRMapSnapshot> overlay in self.overlays) {
|
|
457
|
+
if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
|
|
458
|
+
[overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
for (id <MKAnnotation> annotation in self.annotations) {
|
|
464
|
+
CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
|
|
465
|
+
|
|
466
|
+
MKAnnotationView* anView = [self viewForAnnotation: annotation];
|
|
467
|
+
|
|
468
|
+
if (anView){
|
|
469
|
+
pin = anView;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (CGRectContainsPoint(rect, point)) {
|
|
473
|
+
point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
|
|
474
|
+
point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
|
|
475
|
+
if (pin.image) {
|
|
476
|
+
[pin.image drawAtPoint:point];
|
|
477
|
+
} else {
|
|
478
|
+
CGRect pinRect = CGRectMake(point.x, point.y, pin.bounds.size.width, pin.bounds.size.height);
|
|
479
|
+
[pin drawViewHierarchyInRect:pinRect afterScreenUpdates:NO];
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
485
|
+
|
|
486
|
+
NSData *data;
|
|
487
|
+
if ([format isEqualToString:@"png"]) {
|
|
488
|
+
data = UIImagePNGRepresentation(compositeImage);
|
|
489
|
+
}
|
|
490
|
+
else if([format isEqualToString:@"jpg"]) {
|
|
491
|
+
data = UIImageJPEGRepresentation(compositeImage, quality);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if ([result isEqualToString:@"file"]) {
|
|
495
|
+
[data writeToFile:filePath atomically:YES];
|
|
496
|
+
success(filePath);
|
|
497
|
+
}
|
|
498
|
+
else if ([result isEqualToString:@"base64"]) {
|
|
499
|
+
success([data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
UIGraphicsEndImageContext();
|
|
503
|
+
}];
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
345
507
|
|
|
346
508
|
- (void)setShowsUserLocation:(BOOL)showsUserLocation
|
|
347
509
|
{
|
|
@@ -380,13 +542,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
380
542
|
_userLocationCalloutEnabled = calloutEnabled;
|
|
381
543
|
}
|
|
382
544
|
|
|
383
|
-
- (void)setHandlePanDrag:(BOOL)
|
|
545
|
+
- (void)setHandlePanDrag:(BOOL)handlePanDrag {
|
|
384
546
|
for (UIGestureRecognizer *recognizer in [self gestureRecognizers]) {
|
|
385
547
|
if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
|
|
386
|
-
recognizer.enabled =
|
|
548
|
+
recognizer.enabled = handlePanDrag;
|
|
387
549
|
break;
|
|
388
550
|
}
|
|
389
551
|
}
|
|
552
|
+
_handlePanDrag = handlePanDrag;
|
|
390
553
|
}
|
|
391
554
|
|
|
392
555
|
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated
|
|
@@ -395,7 +558,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
395
558
|
if (!CLLocationCoordinate2DIsValid(region.center)) {
|
|
396
559
|
return;
|
|
397
560
|
}
|
|
398
|
-
|
|
561
|
+
|
|
399
562
|
// If new span values are nil, use old values instead
|
|
400
563
|
if (!region.span.latitudeDelta) {
|
|
401
564
|
region.span.latitudeDelta = self.region.span.latitudeDelta;
|
|
@@ -403,13 +566,27 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
403
566
|
if (!region.span.longitudeDelta) {
|
|
404
567
|
region.span.longitudeDelta = self.region.span.longitudeDelta;
|
|
405
568
|
}
|
|
406
|
-
|
|
569
|
+
|
|
407
570
|
// Animate/move to new position
|
|
408
571
|
[super setRegion:region animated:animated];
|
|
409
572
|
}
|
|
573
|
+
- (void) setRegion:(MKCoordinateRegion)region
|
|
574
|
+
{
|
|
575
|
+
if (!CLLocationCoordinate2DIsValid(region.center)) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
if (!CLLocationCoordinate2DIsValid(_initialRegion.center)) {
|
|
579
|
+
[self setInitialRegion:region];
|
|
580
|
+
}
|
|
581
|
+
[self setRegion:region animated:NO];
|
|
582
|
+
}
|
|
410
583
|
|
|
411
584
|
- (void)setInitialRegion:(MKCoordinateRegion)initialRegion {
|
|
412
|
-
if (!
|
|
585
|
+
if (!CLLocationCoordinate2DIsValid(initialRegion.center)) {
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
_initialRegion = initialRegion;
|
|
589
|
+
if (!_initialRegionSet && _loadingStarted) {
|
|
413
590
|
_initialRegionSet = YES;
|
|
414
591
|
[self setRegion:initialRegion animated:NO];
|
|
415
592
|
}
|
|
@@ -422,9 +599,12 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
422
599
|
|
|
423
600
|
|
|
424
601
|
- (void)setInitialCamera:(MKMapCamera*)initialCamera {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
602
|
+
_initialCamera = initialCamera;
|
|
603
|
+
if (initialCamera){
|
|
604
|
+
if (!_initialCameraSet && _loadingStarted) {
|
|
605
|
+
_initialCameraSet = YES;
|
|
606
|
+
[self setCamera:initialCamera animated:NO];
|
|
607
|
+
}
|
|
428
608
|
}
|
|
429
609
|
}
|
|
430
610
|
|
|
@@ -471,25 +651,25 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
471
651
|
|
|
472
652
|
- (void)setCameraZoomRange:(NSDictionary *)cameraZoomRange {
|
|
473
653
|
if (@available(iOS 13.0, *)) {
|
|
474
|
-
|
|
654
|
+
|
|
475
655
|
if (cameraZoomRange == nil) {
|
|
476
656
|
cameraZoomRange = @{};
|
|
477
657
|
}
|
|
478
|
-
|
|
658
|
+
|
|
479
659
|
NSNumber *minValue = cameraZoomRange[@"minCenterCoordinateDistance"];
|
|
480
660
|
NSNumber *maxValue = cameraZoomRange[@"maxCenterCoordinateDistance"];
|
|
481
|
-
|
|
661
|
+
|
|
482
662
|
if (minValue == nil && maxValue == nil) {
|
|
483
663
|
self.legacyZoomConstraintsEnabled = YES;
|
|
484
|
-
|
|
664
|
+
|
|
485
665
|
MKMapCameraZoomRange *defaultZoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:MKMapCameraZoomDefault maxCenterCoordinateDistance:MKMapCameraZoomDefault];
|
|
486
666
|
[super setCameraZoomRange:defaultZoomRange animated:NO];
|
|
487
|
-
|
|
667
|
+
|
|
488
668
|
return;
|
|
489
669
|
}
|
|
490
|
-
|
|
670
|
+
|
|
491
671
|
MKMapCameraZoomRange *zoomRange = nil;
|
|
492
|
-
|
|
672
|
+
|
|
493
673
|
if (minValue != nil && maxValue != nil) {
|
|
494
674
|
zoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:[minValue doubleValue] maxCenterCoordinateDistance:[maxValue doubleValue]];
|
|
495
675
|
} else if (minValue != nil) {
|
|
@@ -497,61 +677,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
497
677
|
} else if (maxValue != nil) {
|
|
498
678
|
zoomRange = [[MKMapCameraZoomRange alloc] initWithMaxCenterCoordinateDistance:[maxValue doubleValue]];
|
|
499
679
|
}
|
|
500
|
-
|
|
680
|
+
|
|
501
681
|
BOOL animated = [cameraZoomRange[@"animated"] boolValue];
|
|
502
|
-
|
|
682
|
+
|
|
503
683
|
self.legacyZoomConstraintsEnabled = NO;
|
|
504
684
|
[super setCameraZoomRange:zoomRange animated:animated];
|
|
505
685
|
}
|
|
506
686
|
}
|
|
507
687
|
|
|
508
|
-
// Include properties of MKMapView which are only available on iOS 9+
|
|
509
|
-
// and check if their selector is available before calling super method.
|
|
510
|
-
|
|
511
|
-
- (void)setShowsCompass:(BOOL)showsCompass {
|
|
512
|
-
if (self.overlayCompassButton != nil) {
|
|
513
|
-
self.overlayCompassButton.compassVisibility = showsCompass ? MKFeatureVisibilityAdaptive : MKFeatureVisibilityHidden;
|
|
514
|
-
}
|
|
515
|
-
if ([MKMapView instancesRespondToSelector:@selector(setShowsCompass:)]) {
|
|
516
|
-
[super setShowsCompass:showsCompass];
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
- (BOOL)showsCompass {
|
|
521
|
-
if ([MKMapView instancesRespondToSelector:@selector(showsCompass)]) {
|
|
522
|
-
return [super showsCompass];
|
|
523
|
-
} else {
|
|
524
|
-
return NO;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
- (void)setShowsScale:(BOOL)showsScale {
|
|
529
|
-
if ([MKMapView instancesRespondToSelector:@selector(setShowsScale:)]) {
|
|
530
|
-
[super setShowsScale:showsScale];
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
- (BOOL)showsScale {
|
|
535
|
-
if ([MKMapView instancesRespondToSelector:@selector(showsScale)]) {
|
|
536
|
-
return [super showsScale];
|
|
537
|
-
} else {
|
|
538
|
-
return NO;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
- (void)setShowsTraffic:(BOOL)showsTraffic {
|
|
543
|
-
if ([MKMapView instancesRespondToSelector:@selector(setShowsTraffic:)]) {
|
|
544
|
-
[super setShowsTraffic:showsTraffic];
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
- (BOOL)showsTraffic {
|
|
549
|
-
if ([MKMapView instancesRespondToSelector:@selector(showsTraffic)]) {
|
|
550
|
-
return [super showsTraffic];
|
|
551
|
-
} else {
|
|
552
|
-
return NO;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
688
|
|
|
556
689
|
- (void)setScrollEnabled:(BOOL)scrollEnabled {
|
|
557
690
|
self.shouldScrollEnabled = [NSNumber numberWithBool:scrollEnabled];
|
|
@@ -597,7 +730,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
597
730
|
else {
|
|
598
731
|
self.cacheImageView.image = nil;
|
|
599
732
|
self.cacheImageView.hidden = YES;
|
|
600
|
-
|
|
733
|
+
|
|
601
734
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
602
735
|
self.cacheImageView.image = nil;
|
|
603
736
|
self.cacheImageView.hidden = YES;
|
|
@@ -605,18 +738,47 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
605
738
|
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
|
|
606
739
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
607
740
|
UIGraphicsEndImageContext();
|
|
608
|
-
|
|
741
|
+
|
|
609
742
|
self.cacheImageView.image = image;
|
|
610
743
|
self.cacheImageView.hidden = NO;
|
|
611
744
|
});
|
|
612
745
|
}
|
|
613
|
-
|
|
746
|
+
|
|
614
747
|
[self updateScrollEnabled];
|
|
615
748
|
[self updateZoomEnabled];
|
|
616
749
|
[self updateLegalLabelInsets];
|
|
617
750
|
}
|
|
618
751
|
}
|
|
619
752
|
|
|
753
|
+
- (void) listenToMemoryWarnings
|
|
754
|
+
{
|
|
755
|
+
__weak typeof(self) weakSelf = self;
|
|
756
|
+
static dispatch_once_t onceToken;
|
|
757
|
+
static dispatch_source_t source;
|
|
758
|
+
dispatch_once(&onceToken, ^{
|
|
759
|
+
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_WARN|DISPATCH_MEMORYPRESSURE_CRITICAL, dispatch_get_main_queue());
|
|
760
|
+
dispatch_source_set_event_handler(source, ^{
|
|
761
|
+
[weakSelf handleMemoryWarning];
|
|
762
|
+
});
|
|
763
|
+
dispatch_resume(source);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
/*
|
|
767
|
+
hacky way to release all cache
|
|
768
|
+
this is our last chance to release cache before app crash
|
|
769
|
+
*/
|
|
770
|
+
- (void) handleMemoryWarning
|
|
771
|
+
{
|
|
772
|
+
NSLog(@"handleMemoryWarning warning");
|
|
773
|
+
MKMapType type = self.mapType;
|
|
774
|
+
if (type == MKMapTypeSatellite){
|
|
775
|
+
self.mapType = MKMapTypeStandard;
|
|
776
|
+
} else {
|
|
777
|
+
self.mapType = MKMapTypeSatellite;
|
|
778
|
+
}
|
|
779
|
+
self.mapType = type;
|
|
780
|
+
}
|
|
781
|
+
|
|
620
782
|
- (void)updateLegalLabelInsets {
|
|
621
783
|
if (_legalLabel) {
|
|
622
784
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
@@ -660,6 +822,10 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
660
822
|
self.loadingView.hidden = YES;
|
|
661
823
|
}
|
|
662
824
|
}
|
|
825
|
+
_loadingStarted = YES;
|
|
826
|
+
// display initialRegion/Camera
|
|
827
|
+
[self setInitialRegion:_initialRegion];
|
|
828
|
+
[self setInitialCamera:_initialCamera];
|
|
663
829
|
}
|
|
664
830
|
|
|
665
831
|
- (void)finishLoading {
|
|
@@ -706,50 +872,27 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
706
872
|
- (void)layoutSubviews {
|
|
707
873
|
[super layoutSubviews];
|
|
708
874
|
[self cacheViewIfNeeded];
|
|
709
|
-
|
|
710
|
-
if (self.overlayCompassButton == nil) {
|
|
711
|
-
for (UIView *subview in self.subviews) {
|
|
712
|
-
if (![NSStringFromClass(subview.class) isEqualToString:@"MKPassThroughStackView"]) continue;
|
|
713
|
-
self.overlayCompassButton = [MKCompassButton compassButtonWithMapView:self];
|
|
714
|
-
[subview addSubview:self.overlayCompassButton];
|
|
715
|
-
self.overlayCompassButton.frame = CGRectMake(self.overlayCompassButton.frame.origin.x + _compassOffset.x, self.overlayCompassButton.frame.origin.y + _compassOffset.y, self.overlayCompassButton.frame.size.width, self.overlayCompassButton.frame.size.height);
|
|
716
|
-
break;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (self.defaultCompassButton == nil) {
|
|
721
|
-
for (UIView *subview in self.subviews) {
|
|
722
|
-
if (![NSStringFromClass(subview.class) isEqualToString:@"MKPassThroughStackView"]) continue;
|
|
723
|
-
for (UIView *subview2 in subview.subviews) {
|
|
724
|
-
if (![NSStringFromClass(subview2.class) isEqualToString:@"MKCompassView"]) continue;
|
|
725
|
-
self.defaultCompassButton = subview2;
|
|
726
|
-
self.defaultCompassButton.hidden = YES;
|
|
727
|
-
}
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
|
|
732
875
|
}
|
|
733
876
|
|
|
734
877
|
// based on https://medium.com/@dmytrobabych/getting-actual-rotation-and-zoom-level-for-mapkit-mkmapview-e7f03f430aa9
|
|
735
878
|
- (CGFloat)getZoomLevel {
|
|
736
879
|
CGFloat cameraAngle = self.camera.heading;
|
|
737
|
-
|
|
880
|
+
|
|
738
881
|
if (cameraAngle > 270) {
|
|
739
882
|
cameraAngle = 360 - cameraAngle;
|
|
740
883
|
} else if (cameraAngle > 90) {
|
|
741
884
|
cameraAngle = fabs(cameraAngle - 180);
|
|
742
885
|
}
|
|
743
|
-
|
|
886
|
+
|
|
744
887
|
CGFloat angleRad = M_PI * cameraAngle / 180; // map rotation in radians
|
|
745
888
|
CGFloat width = self.frame.size.width;
|
|
746
889
|
CGFloat height = self.frame.size.height;
|
|
747
890
|
CGFloat heightOffset = 20; // the offset (status bar height) which is taken by MapKit into consideration to calculate visible area height
|
|
748
|
-
|
|
891
|
+
|
|
749
892
|
// calculating Longitude span corresponding to normal (non-rotated) width
|
|
750
893
|
CGFloat spanStraight = width * self.region.span.longitudeDelta / (width * cos(angleRad) + (height - heightOffset) * sin(angleRad));
|
|
751
894
|
int normalizingFactor = 512;
|
|
752
|
-
|
|
895
|
+
|
|
753
896
|
return log2(360 * ((width / normalizingFactor) / spanStraight));
|
|
754
897
|
}
|
|
755
898
|
|