[ios, osx] Coordinate formatter
Added a degree-minute-second coordinate formatter for general use. Use this formatter in iosapp and osxapp. Added unit tests for the coordinate formatter and for round-tripping geometry types through NSValue.
This commit is contained in:
committed by
Minh Nguyễn
parent
a852ee24fb
commit
91023f02f8
@@ -63,6 +63,7 @@ custom_categories:
|
||||
- MGLCoordinateBoundsIsEmpty
|
||||
- MGLCoordinateBoundsMake
|
||||
- MGLCoordinateBoundsOffset
|
||||
- MGLCoordinateFormatter
|
||||
- MGLCoordinateSpan
|
||||
- MGLCoordinateSpanEqualToCoordinateSpan
|
||||
- MGLCoordinateSpanMake
|
||||
@@ -70,3 +71,4 @@ custom_categories:
|
||||
- MGLDegreesFromRadians
|
||||
- MGLRadiansFromDegrees
|
||||
- MGLStringFromCoordinateBounds
|
||||
- NSValue(MGLGeometryAdditions)
|
||||
|
||||
31
platform/darwin/include/MGLCoordinateFormatter.h
Normal file
31
platform/darwin/include/MGLCoordinateFormatter.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#import "MGLTypes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
The `MGLCoordinateFormatter` class provides properly formatted descriptions of
|
||||
geographic coordinate pairs. Use this class to create localized coordinate
|
||||
strings when displaying location information to users.
|
||||
*/
|
||||
@interface MGLCoordinateFormatter : NSFormatter
|
||||
|
||||
/**
|
||||
Returns a coordinate string for the provided value.
|
||||
|
||||
@param coordinate The coordinate’s value.
|
||||
@return The coordinate string appropriately formatted for the formatter’s
|
||||
locale.
|
||||
*/
|
||||
- (NSString *)stringFromCoordinate:(CLLocationCoordinate2D)coordinate;
|
||||
|
||||
/**
|
||||
This method is not supported for the `MGLCoordinateFormatter` class.
|
||||
*/
|
||||
- (BOOL)getObjectValue:(out id __nullable * __nullable)obj forString:(NSString *)string errorDescription:(out NSString * __nullable * __nullable)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
60
platform/darwin/src/MGLCoordinateFormatter.m
Normal file
60
platform/darwin/src/MGLCoordinateFormatter.m
Normal file
@@ -0,0 +1,60 @@
|
||||
#import "MGLCoordinateFormatter.h"
|
||||
|
||||
#import "MGLGeometry.h"
|
||||
|
||||
@implementation MGLCoordinateFormatter {
|
||||
NSNumberFormatter *_numberFormatter;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_numberFormatter = [[NSNumberFormatter alloc] init];
|
||||
_numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
_numberFormatter.maximumFractionDigits = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)stringFromCoordinate:(CLLocationCoordinate2D)coordinate {
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"%@, %@", @"Latitude, longitude format"),
|
||||
[self stringFromLocationDegrees:coordinate.latitude
|
||||
positiveFormat:NSLocalizedString(@"%@N", @"North latitude format")
|
||||
negativeFormat:NSLocalizedString(@"%@S", @"South latitude format")],
|
||||
[self stringFromLocationDegrees:coordinate.longitude
|
||||
positiveFormat:NSLocalizedString(@"%@E", @"East longitude format")
|
||||
negativeFormat:NSLocalizedString(@"%@W", @"West longitude format")]];
|
||||
}
|
||||
|
||||
- (NSString *)stringFromLocationDegrees:(CLLocationDegrees)degrees positiveFormat:(NSString *)positiveFormat negativeFormat:(NSString *)negativeFormat {
|
||||
CLLocationDegrees minutes = (fabs(degrees) - floor(fabs(degrees))) * 60;
|
||||
CLLocationDegrees seconds = (minutes - floor(minutes)) * 60;
|
||||
|
||||
NSMutableString *string = [NSMutableString stringWithFormat:NSLocalizedString(@"%@°", @"Degrees of arc format"),
|
||||
[_numberFormatter stringFromNumber:@(floor(fabs(degrees)))]];
|
||||
if (trunc(minutes) > 0 || trunc(seconds) > 0) {
|
||||
[string appendFormat:NSLocalizedString(@"%@′", @"Arcminutes format"),
|
||||
[_numberFormatter stringFromNumber:@(floor(minutes))]];
|
||||
}
|
||||
if (trunc(seconds) > 0) {
|
||||
[string appendFormat:NSLocalizedString(@"%@″", @"Arcseconds format"),
|
||||
[_numberFormatter stringFromNumber:@(seconds)]];
|
||||
}
|
||||
if (degrees == 0) {
|
||||
return string;
|
||||
}
|
||||
return [NSString stringWithFormat:degrees > 0 ? positiveFormat : negativeFormat, string];
|
||||
}
|
||||
|
||||
- (nullable NSString *)stringForObjectValue:(id)obj {
|
||||
if (![obj isKindOfClass:[NSValue class]]) {
|
||||
return nil;
|
||||
}
|
||||
return [self stringFromCoordinate:[obj MGLCoordinateValue]];
|
||||
}
|
||||
|
||||
- (BOOL)getObjectValue:(out id __nullable * __nullable)obj forString:(NSString *)string errorDescription:(out NSString * __nullable * __nullable)error {
|
||||
NSAssert(NO, @"-getObjectValue:forString:errorDescription: has not been implemented");
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
15
platform/darwin/test/MGLCoordinateFormatterTests.m
Normal file
15
platform/darwin/test/MGLCoordinateFormatterTests.m
Normal file
@@ -0,0 +1,15 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface MGLCoordinateFormatterTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLCoordinateFormatterTests
|
||||
|
||||
- (void)testStrings {
|
||||
MGLCoordinateFormatter *formatter = [[MGLCoordinateFormatter alloc] init];
|
||||
XCTAssertEqualObjects([formatter stringFromCoordinate:CLLocationCoordinate2DMake(38.9131982, -77.0325453144239)], @"38°54′48″N, 77°1′57″W");
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -52,4 +52,29 @@
|
||||
XCTAssertEqualWithAccuracy(18, MGLZoomLevelForAltitude(MGLAltitudeForZoomLevel(18, 60, 40, midSize), 60, 40, midSize), 3);
|
||||
}
|
||||
|
||||
- (void)testGeometryBoxing {
|
||||
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239);
|
||||
CLLocationCoordinate2D roundTrippedCoordinate = [NSValue valueWithMGLCoordinate:coordinate].MGLCoordinateValue;
|
||||
|
||||
XCTAssertEqual(coordinate.latitude, roundTrippedCoordinate.latitude, @"Latitude should round-trip.");
|
||||
XCTAssertEqual(coordinate.longitude, roundTrippedCoordinate.longitude, @"Longitude should round-trip.");
|
||||
|
||||
MGLCoordinateSpan span = MGLCoordinateSpanMake(4.383333333333335, -4.299999999999997);
|
||||
MGLCoordinateSpan roundTrippedSpan = [NSValue valueWithMGLCoordinateSpan:span].MGLCoordinateSpanValue;
|
||||
|
||||
XCTAssertEqual(span.latitudeDelta, roundTrippedSpan.latitudeDelta, @"Latitude delta should round-trip.");
|
||||
XCTAssertEqual(span.longitudeDelta, roundTrippedSpan.longitudeDelta, @"Longitude delta should round-trip.");
|
||||
|
||||
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(38.9131982, -77.0325453144239),
|
||||
CLLocationCoordinate2DMake(37.7757368, -122.4135302));
|
||||
MGLCoordinateBounds roundTrippedBounds = [NSValue valueWithMGLCoordinateBounds:bounds].MGLCoordinateBoundsValue;
|
||||
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.sw],
|
||||
[NSValue valueWithMGLCoordinate:roundTrippedBounds.sw],
|
||||
@"Southwest should round-trip.");
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.ne],
|
||||
[NSValue valueWithMGLCoordinate:roundTrippedBounds.ne],
|
||||
@"Northeast should round-trip.");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,6 +11,8 @@ Mapbox welcomes participation and contributions from everyone. Please read [CON
|
||||
- Setting the `image` property of an MGLAnnotationImage to `nil` resets it to the default red pin image and reclaims resources that can be used to customize additional annotations. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835))
|
||||
- Fixed an issue preventing KVO change notifications from being generated on MGLMapView’s `userTrackingMode` key path when `-setUserTrackingMode:animated:` is called. ([#4724](https://github.com/mapbox/mapbox-gl-native/pull/4724))
|
||||
- Rendering now occurs on the main thread, fixing a hang when calling `-[MGLMapView styleURL]` before the map view has fully loaded or while the application is in the background. ([#2909](https://github.com/mapbox/mapbox-gl-native/pull/2909))
|
||||
- Added category methods on NSValue for converting to and from the structure types defined in MGLGeometry.h. ([#4802](https://github.com/mapbox/mapbox-gl-native/pull/4802))
|
||||
- Added MGLCoordinateFormatter for converting geographic coordinates into display strings. ([#4802](https://github.com/mapbox/mapbox-gl-native/pull/4802))
|
||||
- Added a `-reloadStyle:` action to MGLMapView to force a reload of the current style. ([#4728](https://github.com/mapbox/mapbox-gl-native/pull/4728))
|
||||
- A more specific user agent string is now sent with style and tile requests. ([#4012](https://github.com/mapbox/mapbox-gl-native/pull/4012))
|
||||
- Mapbox Telemetry is automatically disabled while the host application is running in the iOS Simulator. ([#4726](https://github.com/mapbox/mapbox-gl-native/pull/4726))
|
||||
|
||||
@@ -450,7 +450,7 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
|
||||
point.coordinate = [self.mapView convertPoint:[longPress locationInView:longPress.view]
|
||||
toCoordinateFromView:self.mapView];
|
||||
point.title = @"Dropped Marker";
|
||||
point.subtitle = [NSString stringWithFormat:@"lat: %.3f, lon: %.3f", point.coordinate.latitude, point.coordinate.longitude];
|
||||
point.subtitle = [[[MGLCoordinateFormatter alloc] init] stringFromCoordinate:point.coordinate];
|
||||
[self.mapView addAnnotation:point];
|
||||
[self.mapView selectAnnotation:point animated:YES];
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "MGLAnnotation.h"
|
||||
#import "MGLAnnotationImage.h"
|
||||
#import "MGLCalloutView.h"
|
||||
#import "MGLCoordinateFormatter.h"
|
||||
#import "MGLMapCamera.h"
|
||||
#import "MGLGeometry.h"
|
||||
#import "MGLMapView.h"
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
DA2E88631CC0382C00F24E7B /* MGLOfflineRegionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */; };
|
||||
DA2E88641CC0382C00F24E7B /* MGLOfflineStorageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2E885F1CC0382C00F24E7B /* MGLOfflineStorageTests.m */; };
|
||||
DA2E88651CC0382C00F24E7B /* MGLStyleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */; };
|
||||
DA35A29E1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */; };
|
||||
DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */; };
|
||||
DA35A2AA1CCA058D00E826B2 /* MGLCoordinateFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */; };
|
||||
DA4A26941CB6E337000B7809 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC9561CB6C1C2006E619F /* Main.storyboard */; };
|
||||
DA4A26951CB6E337000B7809 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC95B1CB6C1C2006E619F /* LaunchScreen.storyboard */; };
|
||||
DA8847D91CBAF91600AB86E3 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
|
||||
@@ -269,6 +274,9 @@
|
||||
DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLOfflineRegionTests.m; path = ../../darwin/test/MGLOfflineRegionTests.m; sourceTree = "<group>"; };
|
||||
DA2E885F1CC0382C00F24E7B /* MGLOfflineStorageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLOfflineStorageTests.m; path = ../../darwin/test/MGLOfflineStorageTests.m; sourceTree = "<group>"; };
|
||||
DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLStyleTests.mm; path = ../../darwin/test/MGLStyleTests.mm; sourceTree = "<group>"; };
|
||||
DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLCoordinateFormatter.h; path = include/MGLCoordinateFormatter.h; sourceTree = "<group>"; };
|
||||
DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCoordinateFormatter.m; path = src/MGLCoordinateFormatter.m; sourceTree = "<group>"; };
|
||||
DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCoordinateFormatterTests.m; path = ../../darwin/test/MGLCoordinateFormatterTests.m; sourceTree = "<group>"; };
|
||||
DA4A26961CB6E795000B7809 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA8847D21CBAF91600AB86E3 /* Mapbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA8847D61CBAF91600AB86E3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@@ -503,6 +511,7 @@
|
||||
DA2E88521CC036F400F24E7B /* SDK Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */,
|
||||
DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */,
|
||||
DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */,
|
||||
DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */,
|
||||
@@ -534,6 +543,8 @@
|
||||
DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */,
|
||||
DA8848001CBAFA6200AB86E3 /* MGLAccountManager.m */,
|
||||
DA8847E01CBAFA5100AB86E3 /* MGLAnnotation.h */,
|
||||
DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */,
|
||||
DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */,
|
||||
DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */,
|
||||
DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */,
|
||||
DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */,
|
||||
@@ -741,6 +752,7 @@
|
||||
DA88483D1CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h in Headers */,
|
||||
DA17BE301CC4BAC300402C41 /* MGLMapView_Internal.h in Headers */,
|
||||
DA88481E1CBAFA6200AB86E3 /* MGLMultiPoint_Private.h in Headers */,
|
||||
DA35A29E1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
|
||||
DA8847F71CBAFA5100AB86E3 /* MGLOverlay.h in Headers */,
|
||||
DA88488B1CBB037E00AB86E3 /* SMCalloutView.h in Headers */,
|
||||
DA8847FE1CBAFA5100AB86E3 /* MGLTypes.h in Headers */,
|
||||
@@ -771,6 +783,7 @@
|
||||
files = (
|
||||
DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */,
|
||||
DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */,
|
||||
DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
|
||||
DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */,
|
||||
DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */,
|
||||
DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */,
|
||||
@@ -1019,6 +1032,7 @@
|
||||
DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */,
|
||||
DA2E88641CC0382C00F24E7B /* MGLOfflineStorageTests.m in Sources */,
|
||||
DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */,
|
||||
DA35A2AA1CCA058D00E826B2 /* MGLCoordinateFormatterTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1038,6 +1052,7 @@
|
||||
DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */,
|
||||
DA8848281CBAFA6200AB86E3 /* MGLShape.m in Sources */,
|
||||
DA8848321CBAFA6200AB86E3 /* NSString+MGLAdditions.m in Sources */,
|
||||
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
|
||||
DA8848291CBAFA6200AB86E3 /* MGLStyle.mm in Sources */,
|
||||
DA88481C1CBAFA6200AB86E3 /* MGLGeometry.mm in Sources */,
|
||||
DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */,
|
||||
@@ -1071,6 +1086,7 @@
|
||||
DAA4E41D1CBB730400178DFB /* MGLGeometry.mm in Sources */,
|
||||
DAA4E41F1CBB730400178DFB /* MGLMultiPoint.mm in Sources */,
|
||||
DAA4E4281CBB730400178DFB /* MGLTypes.m in Sources */,
|
||||
DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
|
||||
DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */,
|
||||
DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */,
|
||||
DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */,
|
||||
|
||||
@@ -2,21 +2,27 @@
|
||||
|
||||
#import "LocationCoordinate2DTransformer.h"
|
||||
#import "TimeIntervalTransformer.h"
|
||||
#import "NSValue+Additions.h"
|
||||
|
||||
#import <Mapbox/Mapbox.h>
|
||||
|
||||
static MGLCoordinateFormatter *DroppedPinCoordinateFormatter;
|
||||
|
||||
@implementation DroppedPinAnnotation {
|
||||
NSTimer *_timer;
|
||||
NSTimeInterval _priorShownTimeInterval;
|
||||
NSDate *_dateShown;
|
||||
|
||||
NSValueTransformer *_coordinateTransformer;
|
||||
NSValueTransformer *_timeIntervalTransformer;
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
if (self == [DroppedPinAnnotation class]) {
|
||||
DroppedPinCoordinateFormatter = [[MGLCoordinateFormatter alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_coordinateTransformer = [NSValueTransformer valueTransformerForName:
|
||||
NSStringFromClass([LocationCoordinate2DTransformer class])];
|
||||
_timeIntervalTransformer = [NSValueTransformer valueTransformerForName:
|
||||
NSStringFromClass([TimeIntervalTransformer class])];
|
||||
[self update:nil];
|
||||
@@ -54,8 +60,7 @@
|
||||
}
|
||||
|
||||
- (void)update:(NSTimer *)timer {
|
||||
NSString *coordinate = [_coordinateTransformer transformedValue:
|
||||
[NSValue valueWithCLLocationCoordinate2D:self.coordinate]];
|
||||
NSString *coordinate = [DroppedPinCoordinateFormatter stringFromCoordinate:self.coordinate];
|
||||
NSString *elapsedTime = [_timeIntervalTransformer transformedValue:@(self.elapsedShownTime)];
|
||||
self.subtitle = [NSString stringWithFormat:@"%@\nSelected for %@", coordinate, elapsedTime];
|
||||
}
|
||||
|
||||
@@ -1,26 +1,11 @@
|
||||
#import "LocationCoordinate2DTransformer.h"
|
||||
|
||||
#import "NSValue+Additions.h"
|
||||
#import <Mapbox/Mapbox.h>
|
||||
|
||||
NSString *StringFromDegrees(CLLocationDegrees degrees, char positiveDirection, char negativeDirection) {
|
||||
double minutes = (degrees - floor(degrees)) * 60;
|
||||
double seconds = (minutes - floor(minutes)) * 60;
|
||||
|
||||
NSMutableString *string = [NSMutableString stringWithFormat:@"%.0f°", fabs(degrees)];
|
||||
if (floor(minutes) || floor(seconds)) {
|
||||
[string appendFormat:@"%.0f′", minutes];
|
||||
}
|
||||
if (floor(seconds)) {
|
||||
[string appendFormat:@"%.0f″", seconds];
|
||||
}
|
||||
if (degrees) {
|
||||
[string appendFormat:@"%c", degrees > 0 ? positiveDirection : negativeDirection];
|
||||
}
|
||||
return string;
|
||||
@implementation LocationCoordinate2DTransformer {
|
||||
MGLCoordinateFormatter *_coordinateFormatter;
|
||||
}
|
||||
|
||||
@implementation LocationCoordinate2DTransformer
|
||||
|
||||
+ (Class)transformedValueClass {
|
||||
return [NSString class];
|
||||
}
|
||||
@@ -29,14 +14,18 @@ NSString *StringFromDegrees(CLLocationDegrees degrees, char positiveDirection, c
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_coordinateFormatter = [[MGLCoordinateFormatter alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)transformedValue:(id)value {
|
||||
if (![value isKindOfClass:[NSValue class]]) {
|
||||
return nil;
|
||||
}
|
||||
CLLocationCoordinate2D coordinate = [value CLLocationCoordinate2DValue];
|
||||
return [NSString stringWithFormat:@"%@, %@",
|
||||
StringFromDegrees(coordinate.latitude, 'N', 'S'),
|
||||
StringFromDegrees(coordinate.longitude, 'E', 'W')];
|
||||
return [_coordinateFormatter stringForObjectValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "DroppedPinAnnotation.h"
|
||||
#import "NSValue+Additions.h"
|
||||
|
||||
#import <Mapbox/Mapbox.h>
|
||||
|
||||
@@ -222,7 +221,7 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
|
||||
|
||||
// Temporarily set the display name to the default center coordinate instead
|
||||
// of “Untitled” until the binding kicks in.
|
||||
NSValue *coordinateValue = [NSValue valueWithCLLocationCoordinate2D:self.mapView.centerCoordinate];
|
||||
NSValue *coordinateValue = [NSValue valueWithMGLCoordinate:self.mapView.centerCoordinate];
|
||||
self.displayName = [[NSValueTransformer valueTransformerForName:@"LocationCoordinate2DTransformer"]
|
||||
transformedValue:coordinateValue];
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
@interface NSValue (Additions)
|
||||
|
||||
+ (instancetype)valueWithCLLocationCoordinate2D:(CLLocationCoordinate2D)coordinate;
|
||||
|
||||
@property (readonly) CLLocationCoordinate2D CLLocationCoordinate2DValue;
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
#import "NSValue+Additions.h"
|
||||
|
||||
@implementation NSValue (Additions)
|
||||
|
||||
+ (instancetype)valueWithCLLocationCoordinate2D:(CLLocationCoordinate2D)coordinate {
|
||||
return [self valueWithBytes:&coordinate objCType:@encode(CLLocationCoordinate2D)];
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)CLLocationCoordinate2DValue {
|
||||
CLLocationCoordinate2D coordinate;
|
||||
[self getValue:&coordinate];
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,7 +1,5 @@
|
||||
#import "TimeIntervalTransformer.h"
|
||||
|
||||
#import "NSValue+Additions.h"
|
||||
|
||||
@implementation TimeIntervalTransformer
|
||||
|
||||
+ (Class)transformedValueClass {
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
52BECB0A1CC5A26F009CD791 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */; };
|
||||
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; };
|
||||
DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */; };
|
||||
DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E961CC2E3400062CAFB /* AppDelegate.m */; };
|
||||
DA839E9A1CC2E3400062CAFB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E991CC2E3400062CAFB /* main.m */; };
|
||||
DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E9C1CC2E3400062CAFB /* MapDocument.m */; };
|
||||
@@ -18,7 +21,6 @@
|
||||
DAE6C2E21CC304F900DB3429 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C2E11CC304F900DB3429 /* Credits.rtf */; };
|
||||
DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */; };
|
||||
DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E61CC3050F00DB3429 /* LocationCoordinate2DTransformer.m */; };
|
||||
DAE6C2EF1CC3050F00DB3429 /* NSValue+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E81CC3050F00DB3429 /* NSValue+Additions.m */; };
|
||||
DAE6C2F01CC3050F00DB3429 /* OfflinePackNameValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */; };
|
||||
DAE6C2F11CC3050F00DB3429 /* TimeIntervalTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2EC1CC3050F00DB3429 /* TimeIntervalTransformer.m */; };
|
||||
DAE6C3321CC30DB200DB3429 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3281CC30DB200DB3429 /* Mapbox.framework */; };
|
||||
@@ -134,6 +136,9 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLCoordinateFormatter.h; path = include/MGLCoordinateFormatter.h; sourceTree = "<group>"; };
|
||||
DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCoordinateFormatter.m; path = src/MGLCoordinateFormatter.m; sourceTree = "<group>"; };
|
||||
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCoordinateFormatterTests.m; path = ../../darwin/test/MGLCoordinateFormatterTests.m; sourceTree = "<group>"; };
|
||||
DA839E921CC2E3400062CAFB /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA839E951CC2E3400062CAFB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
DA839E961CC2E3400062CAFB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
@@ -150,8 +155,6 @@
|
||||
DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DroppedPinAnnotation.m; sourceTree = "<group>"; };
|
||||
DAE6C2E51CC3050F00DB3429 /* LocationCoordinate2DTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocationCoordinate2DTransformer.h; sourceTree = "<group>"; };
|
||||
DAE6C2E61CC3050F00DB3429 /* LocationCoordinate2DTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocationCoordinate2DTransformer.m; sourceTree = "<group>"; };
|
||||
DAE6C2E71CC3050F00DB3429 /* NSValue+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+Additions.h"; sourceTree = "<group>"; };
|
||||
DAE6C2E81CC3050F00DB3429 /* NSValue+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+Additions.m"; sourceTree = "<group>"; };
|
||||
DAE6C2E91CC3050F00DB3429 /* OfflinePackNameValueTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OfflinePackNameValueTransformer.h; sourceTree = "<group>"; };
|
||||
DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OfflinePackNameValueTransformer.m; sourceTree = "<group>"; };
|
||||
DAE6C2EB1CC3050F00DB3429 /* TimeIntervalTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeIntervalTransformer.h; sourceTree = "<group>"; };
|
||||
@@ -222,7 +225,7 @@
|
||||
DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = mapbox.pdf; path = src/resources/mapbox.pdf; sourceTree = SOURCE_ROOT; };
|
||||
DAE6C3BD1CC31F2E00DB3429 /* MGLAnnotationCallout.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MGLAnnotationCallout.xib; path = src/resources/MGLAnnotationCallout.xib; sourceTree = SOURCE_ROOT; };
|
||||
DAE6C3C11CC31F4500DB3429 /* Mapbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mapbox.h; sourceTree = "<group>"; };
|
||||
DAE6C3C51CC31F9100DB3429 /* mbgl.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = mbgl.xcconfig; path = "../../build/osx/mbgl.xcconfig"; sourceTree = "<group>"; };
|
||||
DAE6C3C51CC31F9100DB3429 /* mbgl.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = mbgl.xcconfig; path = ../../build/osx/mbgl.xcconfig; sourceTree = "<group>"; };
|
||||
DAE6C3C61CC3499100DB3429 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
|
||||
DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLGeometryTests.mm; path = ../../darwin/test/MGLGeometryTests.mm; sourceTree = "<group>"; };
|
||||
DAE6C3C91CC34BD800DB3429 /* MGLOfflinePackTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLOfflinePackTests.m; path = ../../darwin/test/MGLOfflinePackTests.m; sourceTree = "<group>"; };
|
||||
@@ -297,8 +300,6 @@
|
||||
DA839E9B1CC2E3400062CAFB /* MapDocument.h */,
|
||||
DA839E9C1CC2E3400062CAFB /* MapDocument.m */,
|
||||
DA839E9E1CC2E3400062CAFB /* MapDocument.xib */,
|
||||
DAE6C2E71CC3050F00DB3429 /* NSValue+Additions.h */,
|
||||
DAE6C2E81CC3050F00DB3429 /* NSValue+Additions.m */,
|
||||
DAE6C2E91CC3050F00DB3429 /* OfflinePackNameValueTransformer.h */,
|
||||
DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */,
|
||||
DAE6C2EB1CC3050F00DB3429 /* TimeIntervalTransformer.h */,
|
||||
@@ -350,6 +351,7 @@
|
||||
DAE6C3371CC30DB200DB3429 /* SDK Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */,
|
||||
DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */,
|
||||
DAE6C3C91CC34BD800DB3429 /* MGLOfflinePackTests.m */,
|
||||
DAE6C3CA1CC34BD800DB3429 /* MGLOfflineRegionTests.m */,
|
||||
@@ -368,6 +370,8 @@
|
||||
DAE6C36A1CC31E2A00DB3429 /* MGLAccountManager_Private.h */,
|
||||
DAE6C36B1CC31E2A00DB3429 /* MGLAccountManager.m */,
|
||||
DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */,
|
||||
DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */,
|
||||
DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */,
|
||||
DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
|
||||
DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */,
|
||||
DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */,
|
||||
@@ -475,6 +479,7 @@
|
||||
DAE6C3661CC31E0400DB3429 /* MGLShape.h in Headers */,
|
||||
DAE6C3C21CC31F4500DB3429 /* Mapbox.h in Headers */,
|
||||
DAE6C3641CC31E0400DB3429 /* MGLPolygon.h in Headers */,
|
||||
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */,
|
||||
DAE6C3621CC31E0400DB3429 /* MGLOverlay.h in Headers */,
|
||||
DAE6C3651CC31E0400DB3429 /* MGLPolyline.h in Headers */,
|
||||
DAE6C39A1CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.h in Headers */,
|
||||
@@ -635,7 +640,6 @@
|
||||
DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */,
|
||||
DAE6C2F11CC3050F00DB3429 /* TimeIntervalTransformer.m in Sources */,
|
||||
DA839E9A1CC2E3400062CAFB /* main.m in Sources */,
|
||||
DAE6C2EF1CC3050F00DB3429 /* NSValue+Additions.m in Sources */,
|
||||
DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */,
|
||||
DAE6C2F01CC3050F00DB3429 /* OfflinePackNameValueTransformer.m in Sources */,
|
||||
);
|
||||
@@ -659,6 +663,7 @@
|
||||
DAE6C3BA1CC31EF300DB3429 /* MGLOpenGLLayer.mm in Sources */,
|
||||
DAE6C38A1CC31E2A00DB3429 /* MGLMultiPoint.mm in Sources */,
|
||||
DAE6C3961CC31E2A00DB3429 /* MGLTypes.m in Sources */,
|
||||
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */,
|
||||
DAE6C3881CC31E2A00DB3429 /* MGLMapCamera.mm in Sources */,
|
||||
DAE6C3911CC31E2A00DB3429 /* MGLPolygon.mm in Sources */,
|
||||
DAE6C39B1CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.m in Sources */,
|
||||
@@ -679,6 +684,7 @@
|
||||
DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */,
|
||||
DAE6C3D51CC34C9900DB3429 /* MGLOfflineStorageTests.m in Sources */,
|
||||
DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */,
|
||||
DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import <Mapbox/MGLAccountManager.h>
|
||||
#import <Mapbox/MGLAnnotation.h>
|
||||
#import <Mapbox/MGLAnnotationImage.h>
|
||||
#import <Mapbox/MGLCoordinateFormatter.h>
|
||||
#import <Mapbox/MGLGeometry.h>
|
||||
#import <Mapbox/MGLMapCamera.h>
|
||||
#import <Mapbox/MGLMapView.h>
|
||||
|
||||
Reference in New Issue
Block a user