From c63de5e2a58df1ecf16b4be62a9c314b2770b627 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Mon, 30 Nov 2015 05:07:43 -0800 Subject: [PATCH] Fixed MapView crash on iOS 8 and earlier Summary: public [MKPinAnnotationView redPinColor] is only supported on iOS 9 and later. This caused React Native to crash on iOS 8 and earlier. This fixes the crash by providing a forked implementation for different OS versions. Reviewed By: tadeuzagallo, javache Differential Revision: D2702737 fb-gh-sync-id: cd8984f1f3d42989001f3c571e325f1b4ba09ac8 --- Libraries/Components/MapView/MapView.js | 10 ++++- React/Views/RCTMapManager.m | 56 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/Libraries/Components/MapView/MapView.js b/Libraries/Components/MapView/MapView.js index 9324a2aec..2dc4fdf30 100644 --- a/Libraries/Components/MapView/MapView.js +++ b/Libraries/Components/MapView/MapView.js @@ -219,6 +219,10 @@ var MapView = React.createClass({ * The pin color. This can be any valid color string, or you can use one * of the predefined PinColors constants. Applies to both standard pins * and custom pin images. + * + * Note that on iOS 8 and earlier, only the standard PinColor constants + * are supported for regualr pins. For custom pin images, any tintColor + * value is supported on all iOS versions. * @platform ios */ tintColor: React.PropTypes.string, @@ -373,8 +377,10 @@ var MapView = React.createClass({ /** * Standard iOS MapView pin color constants, to be used with the - * `annotation.tintColor` property. You are not obliged to use these, - * but they are useful for matching the standard iOS look and feel. + * `annotation.tintColor` property. On iOS 8 and earlier these are the + * only supported values when using regular pins. On iOS 9 and later + * you are not obliged to use these, but they are useful for matching + * the standard iOS look and feel. */ let PinColors = RCTMapConstants && RCTMapConstants.PinColors; MapView.PinColors = PinColors && { diff --git a/React/Views/RCTMapManager.m b/React/Views/RCTMapManager.m index 6c22c6b16..e662d4868 100644 --- a/React/Views/RCTMapManager.m +++ b/React/Views/RCTMapManager.m @@ -23,6 +23,24 @@ static NSString *const RCTMapViewKey = @"MapView"; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0 + +static NSString *const RCTMapPinRed = @"#ff3b30"; +static NSString *const RCTMapPinGreen = @"#4cd964"; +static NSString *const RCTMapPinPurple = @"#c969e0"; + +@implementation RCTConvert (MKPinAnnotationColor) + +RCT_ENUM_CONVERTER(MKPinAnnotationColor, (@{ + RCTMapPinRed: @(MKPinAnnotationColorRed), + RCTMapPinGreen: @(MKPinAnnotationColorGreen), + RCTMapPinPurple: @(MKPinAnnotationColorPurple) +}), MKPinAnnotationColorRed, unsignedIntegerValue) + +@end + +#endif + @interface RCTMapManager() @end @@ -60,11 +78,29 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap) - (NSDictionary *)constantsToExport { + NSString *red, *green, *purple; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0 + + if (![MKPinAnnotationView respondsToSelector:@selector(redPinColor)]) { + red = RCTMapPinRed; + green = RCTMapPinGreen; + purple = RCTMapPinPurple; + } else + +#endif + + { + red = RCTColorToHexString([MKPinAnnotationView redPinColor].CGColor); + green = RCTColorToHexString([MKPinAnnotationView greenPinColor].CGColor); + purple = RCTColorToHexString([MKPinAnnotationView purplePinColor].CGColor); + } + return @{ @"PinColors": @{ - @"RED": RCTColorToHexString([MKPinAnnotationView redPinColor].CGColor), - @"GREEN": RCTColorToHexString([MKPinAnnotationView greenPinColor].CGColor), - @"PURPLE": RCTColorToHexString([MKPinAnnotationView purplePinColor].CGColor), + @"RED": red, + @"GREEN": green, + @"PURPLE": purple, } }; } @@ -127,7 +163,19 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap) NSString *reuseIdentifier = NSStringFromClass([MKPinAnnotationView class]); annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdentifier] ?: [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]; ((MKPinAnnotationView *)annotationView).animatesDrop = annotation.animateDrop; - ((MKPinAnnotationView *)annotationView).pinTintColor = annotation.tintColor ?: [MKPinAnnotationView redPinColor]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0 + + if (![annotationView respondsToSelector:@selector(pinTintColor)]) { + NSString *hexColor = annotation.tintColor ? RCTColorToHexString(annotation.tintColor.CGColor) : RCTMapPinRed; + ((MKPinAnnotationView *)annotationView).pinColor = [RCTConvert MKPinAnnotationColor:hexColor]; + } else + +#endif + + { + ((MKPinAnnotationView *)annotationView).pinTintColor = annotation.tintColor ?: [MKPinAnnotationView redPinColor]; + } } annotationView.canShowCallout = true;