diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-04-22 00:17:39 -0700 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-04-22 11:13:03 -0700 |
commit | 91023f02f85ad243f867a2fb920699c3e1659f94 (patch) | |
tree | 4f3e68615c6a6562e74a2a21d6069ce788993c90 | |
parent | a852ee24fbf6c883b7f64bad9883937eb7b8d80d (diff) | |
download | qtlocation-mapboxgl-91023f02f85ad243f867a2fb920699c3e1659f94.tar.gz |
[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.
-rw-r--r-- | .jazzy.yaml | 2 | ||||
-rw-r--r-- | platform/darwin/include/MGLCoordinateFormatter.h | 31 | ||||
-rw-r--r-- | platform/darwin/src/MGLCoordinateFormatter.m | 60 | ||||
-rw-r--r-- | platform/darwin/test/MGLCoordinateFormatterTests.m | 15 | ||||
-rw-r--r-- | platform/darwin/test/MGLGeometryTests.mm | 25 | ||||
-rw-r--r-- | platform/ios/CHANGELOG.md | 2 | ||||
-rw-r--r-- | platform/ios/app/MBXViewController.m | 2 | ||||
-rw-r--r-- | platform/ios/framework/Mapbox.h | 1 | ||||
-rw-r--r-- | platform/ios/ios.xcodeproj/project.pbxproj | 16 | ||||
-rw-r--r-- | platform/osx/app/DroppedPinAnnotation.m | 17 | ||||
-rw-r--r-- | platform/osx/app/LocationCoordinate2DTransformer.m | 33 | ||||
-rw-r--r-- | platform/osx/app/MapDocument.m | 3 | ||||
-rw-r--r-- | platform/osx/app/NSValue+Additions.h | 10 | ||||
-rw-r--r-- | platform/osx/app/NSValue+Additions.m | 15 | ||||
-rw-r--r-- | platform/osx/app/TimeIntervalTransformer.m | 2 | ||||
-rw-r--r-- | platform/osx/osx.xcodeproj/project.pbxproj | 20 | ||||
-rw-r--r-- | platform/osx/sdk/Mapbox.h | 1 |
17 files changed, 190 insertions, 65 deletions
diff --git a/.jazzy.yaml b/.jazzy.yaml index 216fd82ae2..a6d47f25a2 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -63,6 +63,7 @@ custom_categories: - MGLCoordinateBoundsIsEmpty - MGLCoordinateBoundsMake - MGLCoordinateBoundsOffset + - MGLCoordinateFormatter - MGLCoordinateSpan - MGLCoordinateSpanEqualToCoordinateSpan - MGLCoordinateSpanMake @@ -70,3 +71,4 @@ custom_categories: - MGLDegreesFromRadians - MGLRadiansFromDegrees - MGLStringFromCoordinateBounds + - NSValue(MGLGeometryAdditions) diff --git a/platform/darwin/include/MGLCoordinateFormatter.h b/platform/darwin/include/MGLCoordinateFormatter.h new file mode 100644 index 0000000000..885471c36e --- /dev/null +++ b/platform/darwin/include/MGLCoordinateFormatter.h @@ -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 diff --git a/platform/darwin/src/MGLCoordinateFormatter.m b/platform/darwin/src/MGLCoordinateFormatter.m new file mode 100644 index 0000000000..847b5dfe76 --- /dev/null +++ b/platform/darwin/src/MGLCoordinateFormatter.m @@ -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 diff --git a/platform/darwin/test/MGLCoordinateFormatterTests.m b/platform/darwin/test/MGLCoordinateFormatterTests.m new file mode 100644 index 0000000000..84a17596b1 --- /dev/null +++ b/platform/darwin/test/MGLCoordinateFormatterTests.m @@ -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 diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm index 73af0bb211..b9205e8d9d 100644 --- a/platform/darwin/test/MGLGeometryTests.mm +++ b/platform/darwin/test/MGLGeometryTests.mm @@ -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 diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index e84590e7dc..875b0dd7a6 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -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)) diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index d8bdc6d99e..f6e0cc0ae8 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -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]; } diff --git a/platform/ios/framework/Mapbox.h b/platform/ios/framework/Mapbox.h index 7b233ecac5..68579933b6 100644 --- a/platform/ios/framework/Mapbox.h +++ b/platform/ios/framework/Mapbox.h @@ -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" diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 9215474947..50f2a79dea 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -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 */, diff --git a/platform/osx/app/DroppedPinAnnotation.m b/platform/osx/app/DroppedPinAnnotation.m index a103ec923c..5b19fd7401 100644 --- a/platform/osx/app/DroppedPinAnnotation.m +++ b/platform/osx/app/DroppedPinAnnotation.m @@ -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]; } diff --git a/platform/osx/app/LocationCoordinate2DTransformer.m b/platform/osx/app/LocationCoordinate2DTransformer.m index d9c35b2a1f..aeede23497 100644 --- a/platform/osx/app/LocationCoordinate2DTransformer.m +++ b/platform/osx/app/LocationCoordinate2DTransformer.m @@ -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 diff --git a/platform/osx/app/MapDocument.m b/platform/osx/app/MapDocument.m index aaa04e9914..2a537772b5 100644 --- a/platform/osx/app/MapDocument.m +++ b/platform/osx/app/MapDocument.m @@ -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]; } diff --git a/platform/osx/app/NSValue+Additions.h b/platform/osx/app/NSValue+Additions.h deleted file mode 100644 index 050dbc8132..0000000000 --- a/platform/osx/app/NSValue+Additions.h +++ /dev/null @@ -1,10 +0,0 @@ -#import <Foundation/Foundation.h> -#import <CoreLocation/CoreLocation.h> - -@interface NSValue (Additions) - -+ (instancetype)valueWithCLLocationCoordinate2D:(CLLocationCoordinate2D)coordinate; - -@property (readonly) CLLocationCoordinate2D CLLocationCoordinate2DValue; - -@end diff --git a/platform/osx/app/NSValue+Additions.m b/platform/osx/app/NSValue+Additions.m deleted file mode 100644 index c060602f43..0000000000 --- a/platform/osx/app/NSValue+Additions.m +++ /dev/null @@ -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 diff --git a/platform/osx/app/TimeIntervalTransformer.m b/platform/osx/app/TimeIntervalTransformer.m index e6d7333d25..39177dc5bc 100644 --- a/platform/osx/app/TimeIntervalTransformer.m +++ b/platform/osx/app/TimeIntervalTransformer.m @@ -1,7 +1,5 @@ #import "TimeIntervalTransformer.h" -#import "NSValue+Additions.h" - @implementation TimeIntervalTransformer + (Class)transformedValueClass { diff --git a/platform/osx/osx.xcodeproj/project.pbxproj b/platform/osx/osx.xcodeproj/project.pbxproj index 4854858df8..dc7030a949 100644 --- a/platform/osx/osx.xcodeproj/project.pbxproj +++ b/platform/osx/osx.xcodeproj/project.pbxproj @@ -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; }; diff --git a/platform/osx/sdk/Mapbox.h b/platform/osx/sdk/Mapbox.h index 4a2cd32504..49d5cab728 100644 --- a/platform/osx/sdk/Mapbox.h +++ b/platform/osx/sdk/Mapbox.h @@ -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> |