diff --git a/platform/darwin/src/MLNFeature.mm b/platform/darwin/src/MLNFeature.mm index 84b89b5ed..749836239 100644 --- a/platform/darwin/src/MLNFeature.mm +++ b/platform/darwin/src/MLNFeature.mm @@ -45,13 +45,17 @@ MLN_DEFINE_FEATURE_ATTRIBUTES_GETTER(); } - (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); + return NSDictionaryFeatureForGeometry(@{@"type": @"Empty"}, self.attributes, self.identifier); } - (mbgl::GeoJSON)geoJSONObject { return mbglFeature({[self geometryObject]}, identifier, self.attributes); } +- (mbgl::Geometry)geometryObject { + return mbgl::EmptyGeometry(); +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; identifier = %@, attributes = %@>", diff --git a/platform/darwin/src/MLNFeature_Private.h b/platform/darwin/src/MLNFeature_Private.h index 365341f40..f6961d581 100644 --- a/platform/darwin/src/MLNFeature_Private.h +++ b/platform/darwin/src/MLNFeature_Private.h @@ -53,15 +53,20 @@ NSDictionary *NSDictionaryFeatureForGeometry(NSDictionary *geome NS_ASSUME_NONNULL_END -#define MLN_DEFINE_FEATURE_INIT_WITH_CODER() \ - -(instancetype)initWithCoder : (NSCoder *)decoder { \ - if (self = [super initWithCoder:decoder]) { \ - NSSet *identifierClasses = \ - [NSSet setWithArray:@[ [NSString class], [NSNumber class] ]]; \ - identifier = [decoder decodeObjectOfClasses:identifierClasses forKey:@"identifier"]; \ - _attributes = [decoder decodeObjectOfClass:[NSDictionary class] forKey:@"attributes"]; \ - } \ - return self; \ +#define MLN_DEFINE_FEATURE_INIT_WITH_CODER() \ + -(instancetype)initWithCoder : (NSCoder *)decoder { \ + if (self = [super initWithCoder:decoder]) { \ + NSSet *identifierClasses = \ + [NSSet setWithArray:@[ [NSString class], [NSNumber class] ]]; \ + identifier = [decoder decodeObjectOfClasses:identifierClasses forKey:@"identifier"]; \ + NSSet *attributesClasses = \ + [NSSet setWithArray:@[ [NSDictionary class], [NSArray class] ]]; \ + _attributes = [decoder decodeObjectOfClasses:attributesClasses forKey:@"attributes"]; \ + } \ + return self; \ + } \ + +(BOOL)supportsSecureCoding { \ + return YES; \ } #define MLN_DEFINE_FEATURE_ENCODE() \ diff --git a/platform/darwin/src/MLNGeometry.mm b/platform/darwin/src/MLNGeometry.mm index b1deaa96b..fa8775308 100644 --- a/platform/darwin/src/MLNGeometry.mm +++ b/platform/darwin/src/MLNGeometry.mm @@ -85,6 +85,11 @@ MLNRadianCoordinate2D MLNRadianCoordinateAtDistanceFacingDirection(MLNRadianCoor } CLLocationDirection MLNDirectionBetweenCoordinates(CLLocationCoordinate2D firstCoordinate, CLLocationCoordinate2D secondCoordinate) { + if (MLNEqualFloatWithAccuracy(firstCoordinate.latitude, secondCoordinate.latitude, 1e-8) && MLNEqualFloatWithAccuracy(firstCoordinate.longitude, secondCoordinate.longitude, 1e-8)) { + return 0; + } + + // Ported from https://github.com/mapbox/turf-swift/blob/857e2e8060678ef4a7a9169d4971b0788fdffc37/Turf/Turf.swift#L23-L31 MLNRadianCoordinate2D firstRadianCoordinate = MLNRadianCoordinateFromLocationCoordinate(firstCoordinate); MLNRadianCoordinate2D secondRadianCoordinate = MLNRadianCoordinateFromLocationCoordinate(secondCoordinate); @@ -119,3 +124,8 @@ MLNMatrix4 MLNMatrix4Make(std::array array) { }; return mat4; } + +BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy) +{ + return MAX(left, right) - MIN(left, right) <= accuracy; +} diff --git a/platform/darwin/src/MLNGeometry_Private.h b/platform/darwin/src/MLNGeometry_Private.h index ffff02d8e..b51e3a110 100644 --- a/platform/darwin/src/MLNGeometry_Private.h +++ b/platform/darwin/src/MLNGeometry_Private.h @@ -151,3 +151,5 @@ CLLocationDirection MLNDirectionBetweenCoordinates(CLLocationCoordinate2D firstC CGPoint MLNPointRounded(CGPoint point); MLNMatrix4 MLNMatrix4Make(std::array mat); + +FOUNDATION_EXTERN BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy); diff --git a/platform/darwin/src/MLNMapCamera.mm b/platform/darwin/src/MLNMapCamera.mm index 34a25c70a..5a15bcc25 100644 --- a/platform/darwin/src/MLNMapCamera.mm +++ b/platform/darwin/src/MLNMapCamera.mm @@ -6,11 +6,6 @@ #include -BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy) -{ - return MAX(left, right) - MIN(left, right) <= accuracy; -} - @implementation MLNMapCamera + (BOOL)supportsSecureCoding diff --git a/platform/darwin/src/MLNMultiPoint.mm b/platform/darwin/src/MLNMultiPoint.mm index 523d93378..d5deb4ba9 100644 --- a/platform/darwin/src/MLNMultiPoint.mm +++ b/platform/darwin/src/MLNMultiPoint.mm @@ -28,6 +28,10 @@ return self; } ++ (BOOL)supportsSecureCoding { + return YES; +} + - (instancetype)initWithCoder:(NSCoder *)decoder { MLNLogInfo(@"Initializing with coder."); diff --git a/platform/darwin/src/MLNPointCollection.mm b/platform/darwin/src/MLNPointCollection.mm index 6ce647108..a95845e34 100644 --- a/platform/darwin/src/MLNPointCollection.mm +++ b/platform/darwin/src/MLNPointCollection.mm @@ -14,6 +14,10 @@ NS_ASSUME_NONNULL_BEGIN std::vector _coordinates; } ++ (BOOL)supportsSecureCoding { + return YES; +} + + (instancetype)pointCollectionWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { return [[self alloc] initWithCoordinates:coords count:count]; @@ -33,7 +37,8 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)initWithCoder:(NSCoder *)decoder { MLNLogInfo(@"Initializing with coder.O"); if (self = [super initWithCoder:decoder]) { - NSArray *coordinates = [decoder decodeObjectOfClass:[NSArray class] forKey:@"coordinates"]; + NSSet *coordinatesClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class]]]; + NSArray *coordinates = [decoder decodeObjectOfClasses:coordinatesClasses forKey:@"coordinates"]; _coordinates = [coordinates mgl_coordinates]; } return self; diff --git a/platform/darwin/src/MLNPolygon.mm b/platform/darwin/src/MLNPolygon.mm index 6d29dbcd9..d3818e2d6 100644 --- a/platform/darwin/src/MLNPolygon.mm +++ b/platform/darwin/src/MLNPolygon.mm @@ -13,6 +13,10 @@ @dynamic overlayBounds; ++ (BOOL)supportsSecureCoding { + return YES; +} + + (instancetype)polygonWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { return [self polygonWithCoordinates:coords count:count interiorPolygons:nil]; } @@ -35,7 +39,8 @@ MLNLogInfo(@"Initializng with coder."); self = [super initWithCoder:decoder]; if (self) { - _interiorPolygons = [decoder decodeObjectOfClass:[NSArray class] forKey:@"interiorPolygons"]; + NSSet *polygonClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class], [MLNPolygon class]]]; + _interiorPolygons = [decoder decodeObjectOfClasses:polygonClasses forKey:@"interiorPolygons"]; } return self; } @@ -141,6 +146,10 @@ @synthesize overlayBounds = _overlayBounds; ++ (BOOL)supportsSecureCoding { + return YES; +} + + (instancetype)multiPolygonWithPolygons:(NSArray *)polygons { return [[self alloc] initWithPolygons:polygons]; } @@ -163,7 +172,15 @@ - (instancetype)initWithCoder:(NSCoder *)decoder { MLNLogInfo(@"Initializing with coder."); if (self = [super initWithCoder:decoder]) { - _polygons = [decoder decodeObjectOfClass:[NSArray class] forKey:@"polygons"]; + NSSet *polygonsClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class], [MLNPolygon class]]]; + _polygons = [decoder decodeObjectOfClasses:polygonsClasses forKey:@"polygons"]; + + mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); + + for (MLNPolygon *polygon in _polygons) { + bounds.extend(MLNLatLngBoundsFromCoordinateBounds(polygon.overlayBounds)); + } + _overlayBounds = MLNCoordinateBoundsFromLatLngBounds(bounds); } return self; } diff --git a/platform/darwin/src/MLNPolyline.mm b/platform/darwin/src/MLNPolyline.mm index d380cfbfd..7b0a191ad 100644 --- a/platform/darwin/src/MLNPolyline.mm +++ b/platform/darwin/src/MLNPolyline.mm @@ -13,6 +13,11 @@ @dynamic overlayBounds; ++ (BOOL)supportsSecureCoding +{ + return YES; +} + + (instancetype)polylineWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { @@ -153,10 +158,22 @@ return self; } ++ (BOOL)supportsSecureCoding { + return YES; +} + - (instancetype)initWithCoder:(NSCoder *)decoder { MLNLogInfo(@"Initializing with coder."); if (self = [super initWithCoder:decoder]) { - _polylines = [decoder decodeObjectOfClass:[NSArray class] forKey:@"polylines"]; + NSSet *polylinesClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class], [MLNPolyline class]]]; + _polylines = [decoder decodeObjectOfClasses:polylinesClasses forKey:@"polylines"]; + + mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); + + for (MLNPolyline *polyline in _polylines) { + bounds.extend(MLNLatLngBoundsFromCoordinateBounds(polyline.overlayBounds)); + } + _overlayBounds = MLNCoordinateBoundsFromLatLngBounds(bounds); } return self; } diff --git a/platform/darwin/src/MLNShapeCollection.mm b/platform/darwin/src/MLNShapeCollection.mm index 1e7133832..ca1811bd9 100644 --- a/platform/darwin/src/MLNShapeCollection.mm +++ b/platform/darwin/src/MLNShapeCollection.mm @@ -8,6 +8,10 @@ @implementation MLNShapeCollection ++ (BOOL)supportsSecureCoding { + return YES; +} + + (instancetype)shapeCollectionWithShapes:(NSArray *)shapes { return [[self alloc] initWithShapes:shapes]; } @@ -23,7 +27,8 @@ - (instancetype)initWithCoder:(NSCoder *)decoder { MLNLogInfo(@"Initializing with coder."); if (self = [super initWithCoder:decoder]) { - _shapes = [decoder decodeObjectOfClass:[NSArray class] forKey:@"shapes"]; + NSSet *shapeClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class], [MLNShape class]]]; + _shapes = [decoder decodeObjectOfClasses:shapeClasses forKey:@"shapes"]; } return self; } diff --git a/platform/darwin/src/NSCoder+MLNAdditions.mm b/platform/darwin/src/NSCoder+MLNAdditions.mm index 4199e7820..4df5d1240 100644 --- a/platform/darwin/src/NSCoder+MLNAdditions.mm +++ b/platform/darwin/src/NSCoder+MLNAdditions.mm @@ -10,7 +10,8 @@ } - (std::vector)mgl_decodeLocationCoordinates2DForKey:(NSString *)key { - NSArray *coordinates = [self decodeObjectOfClass:[NSArray class] forKey:key]; + NSSet *coordinateClasses = [NSSet setWithArray:@[[NSArray class], [NSDictionary class]]]; + NSArray *coordinates = [self decodeObjectOfClasses:coordinateClasses forKey:key]; return [coordinates mgl_coordinates]; } @@ -19,7 +20,7 @@ } - (CLLocationCoordinate2D)decodeMLNCoordinateForKey:(NSString *)key { - NSDictionary *coordinate = [self decodeObjectForKey:key]; + NSDictionary *coordinate = [self decodeObjectOfClass:[NSDictionary class] forKey:key]; return CLLocationCoordinate2DMake([coordinate[@"latitude"] doubleValue], [coordinate[@"longitude"] doubleValue]); } diff --git a/platform/darwin/src/NSExpression+MLNAdditions.mm b/platform/darwin/src/NSExpression+MLNAdditions.mm index eb22f9cae..b5f05924c 100644 --- a/platform/darwin/src/NSExpression+MLNAdditions.mm +++ b/platform/darwin/src/NSExpression+MLNAdditions.mm @@ -560,6 +560,16 @@ const MLNExpressionInterpolationMode MLNExpressionInterpolationModeCubicBezier = @implementation NSExpression (MLNAdditions) ++ (NSExpression *)expressionForFunctionHelper:(NSString *)name arguments:(NSArray *)parameters { + if (parameters.count) { + if (@available(iOS 15.5, macOS 12, *)) { + NSExpression *functionExpression = [NSExpression expressionWithFormat:@"sum({})"]; + return [NSExpression expressionForFunction:functionExpression.operand selectorName:name arguments:parameters]; + } + } + return [NSExpression expressionForFunction:name arguments:parameters]; +} + + (NSExpression *)zoomLevelVariableExpression { return [NSExpression expressionForVariable:@"zoomLevel"]; } @@ -599,14 +609,7 @@ const MLNExpressionInterpolationMode MLNExpressionInterpolationModeCubicBezier = + (instancetype)mgl_expressionForSteppingExpression:(nonnull NSExpression *)steppingExpression fromExpression:(nonnull NSExpression *)minimumExpression stops:(nonnull NSExpression *)stops { NSString *selectorName = @"mgl_step:from:stops:"; - if (@available(iOS 15.5, macOS 12, *)) { - return [NSExpression expressionForFunction:steppingExpression - selectorName:selectorName - arguments:@[steppingExpression, minimumExpression, stops]]; - } else { - return [NSExpression expressionForFunction:selectorName - arguments:@[steppingExpression, minimumExpression, stops]]; - } + return [NSExpression expressionForFunctionHelper:selectorName arguments:@[steppingExpression, minimumExpression, stops]]; } + (instancetype)mgl_expressionForInterpolatingExpression:(nonnull NSExpression *)inputExpression withCurveType:(nonnull MLNExpressionInterpolationMode)curveType parameters:(nullable NSExpression *)parameters stops:(nonnull NSExpression *)stops { @@ -614,14 +617,9 @@ const MLNExpressionInterpolationMode MLNExpressionInterpolationModeCubicBezier = NSString *selectorName = @"mgl_interpolate:withCurveType:parameters:stops:"; - if (@available(iOS 15.5, macOS 12, *)) { - return [NSExpression expressionForFunction:inputExpression - selectorName:selectorName - arguments:@[inputExpression, [NSExpression expressionForConstantValue:curveType], sanitizeParams, stops]]; - } else { - return [NSExpression expressionForFunction:selectorName - arguments:@[inputExpression, [NSExpression expressionForConstantValue:curveType], sanitizeParams, stops]]; - } + return [NSExpression expressionForFunctionHelper:selectorName + arguments:@[inputExpression, [NSExpression expressionForConstantValue:curveType], sanitizeParams, stops]]; + } + (instancetype)mgl_expressionForMatchingExpression:(nonnull NSExpression *)inputExpression inDictionary:(nonnull NSDictionary *)matchedExpressions defaultExpression:(nonnull NSExpression *)defaultExpression { @@ -634,17 +632,17 @@ const MLNExpressionInterpolationMode MLNExpressionInterpolationModeCubicBezier = } [optionsArray addObject:defaultExpression]; - return [NSExpression expressionForFunction:@"MLN_MATCH" + return [NSExpression expressionForFunctionHelper:@"MLN_MATCH" arguments:optionsArray]; } + (instancetype)mgl_expressionForAttributedExpressions:(nonnull NSArray *)attributedExpressions { - return [NSExpression expressionForFunction:@"mgl_attributed:" arguments:attributedExpressions]; + return [NSExpression expressionForFunctionHelper:@"mgl_attributed:" arguments:attributedExpressions]; } - (instancetype)mgl_expressionByAppendingExpression:(nonnull NSExpression *)expression { NSExpression *subexpression = [NSExpression expressionForAggregate:@[self, expression]]; - return [NSExpression expressionForFunction:@"mgl_join:" arguments:@[subexpression]]; + return [NSExpression expressionForFunctionHelper:@"mgl_join:" arguments:@[subexpression]]; } static NSDictionary *MLNFunctionNamesByExpressionOperator; @@ -726,7 +724,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { if (![op isKindOfClass:[NSString class]]) { NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(array); - return [NSExpression expressionForFunction:@"MLN_FUNCTION" arguments:subexpressions]; + return [NSExpression expressionForFunctionHelper:@"MLN_FUNCTION" arguments:subexpressions]; } NSArray *argumentObjects = [array subarrayWithRange:NSMakeRange(1, array.count - 1)]; @@ -743,11 +741,11 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { subexpressions = [subexpressions subarrayWithRange:NSMakeRange(1, subexpressions.count - 1)]; } - return [NSExpression expressionForFunction:functionName + return [NSExpression expressionForFunctionHelper:functionName arguments:subexpressions]; } else if ([op isEqualToString:@"collator"]) { // Avoid wrapping collator options object in literal expression. - return [NSExpression expressionForFunction:@"MLN_FUNCTION" arguments:array]; + return [NSExpression expressionForFunctionHelper:@"MLN_FUNCTION" arguments:array]; } else if ([op isEqualToString:@"literal"]) { if ([argumentObjects.firstObject isKindOfClass:[NSArray class]]) { return [NSExpression expressionForAggregate:MLNSubexpressionsWithJSONObjects(argumentObjects.firstObject)]; @@ -778,7 +776,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { #endif } NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(array); - return [NSExpression expressionForFunction:@"MLN_FUNCTION" arguments:subexpressions]; + return [NSExpression expressionForFunctionHelper:@"MLN_FUNCTION" arguments:subexpressions]; } else if ([op isEqualToString:@"to-rgba"]) { NSExpression *operand = [NSExpression expressionWithMLNJSONObject:argumentObjects.firstObject]; @@ -822,7 +820,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { } else if ([op isEqualToString:@"concat"]) { NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(argumentObjects); NSExpression *subexpression = [NSExpression expressionForAggregate:subexpressions]; - return [NSExpression expressionForFunction:@"mgl_join:" arguments:@[subexpression]]; + return [NSExpression expressionForFunctionHelper:@"mgl_join:" arguments:@[subexpression]]; } else if ([op isEqualToString:@"at"]) { NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(argumentObjects); NSExpression *index = subexpressions.firstObject; @@ -832,7 +830,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(argumentObjects); NSExpression *operand = argumentObjects.count > 1 ? subexpressions[1] : [NSExpression expressionForEvaluatedObject]; NSExpression *key = subexpressions.firstObject; - return [NSExpression expressionForFunction:@"mgl_does:have:" arguments:@[operand, key]]; + return [NSExpression expressionForFunctionHelper:@"mgl_does:have:" arguments:@[operand, key]]; } else if ([op isEqualToString:@"interpolate"]) { NSArray *interpolationOptions = argumentObjects.firstObject; NSString *curveType = interpolationOptions.firstObject; @@ -923,7 +921,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { NSPredicate *conditional = [arguments.firstObject constantValue]; return [NSExpression expressionForConditional:conditional trueExpression:arguments[1] falseExpression:arguments[2]]; } - return [NSExpression expressionForFunction:@"MLN_IF" arguments:arguments]; + return [NSExpression expressionForFunctionHelper:@"MLN_IF" arguments:arguments]; } else if ([op isEqualToString:@"match"]) { NSMutableArray *optionsArray = [NSMutableArray array]; @@ -936,7 +934,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { [optionsArray addObject:option]; } - return [NSExpression expressionForFunction:@"MLN_MATCH" + return [NSExpression expressionForFunctionHelper:@"MLN_MATCH" arguments:optionsArray]; } else if ([op isEqualToString:@"format"]) { NSMutableArray *attributedExpressions = [NSMutableArray array]; @@ -955,7 +953,7 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { [attributedExpressions addObject:[NSExpression expressionForConstantValue:attributedExpression]]; } - return [NSExpression expressionForFunction:@"mgl_attributed:" arguments:attributedExpressions]; + return [NSExpression expressionForFunctionHelper:@"mgl_attributed:" arguments:attributedExpressions]; } else if ([op isEqualToString:@"coalesce"]) { NSMutableArray *expressions = [NSMutableArray array]; @@ -963,10 +961,10 @@ NSArray *MLNSubexpressionsWithJSONObjects(NSArray *objects) { [expressions addObject:[NSExpression expressionWithMLNJSONObject:operand]]; } - return [NSExpression expressionWithFormat:@"mgl_coalesce(%@)", expressions]; + return [NSExpression expressionForFunctionHelper:@"mgl_coalesce:" arguments:@[[NSExpression expressionForConstantValue:expressions]]]; } else { NSArray *subexpressions = MLNSubexpressionsWithJSONObjects(array); - return [NSExpression expressionForFunction:@"MLN_FUNCTION" arguments:subexpressions]; + return [NSExpression expressionForFunctionHelper:@"MLN_FUNCTION" arguments:subexpressions]; } } @@ -1599,17 +1597,28 @@ NSDictionary *MLNLocalizedStopDictionary(NSDictionar // If the keypath is `name_zh-Hans`, fallback to `name_zh` to `name`. // CN tiles might using `name_zh-CN` for Simplified Chinese. if ([localizedKeyPath isEqualToString:@"name_zh-Hans"]) { - return [NSExpression expressionWithFormat:@"mgl_coalesce({%K, %K, %K, %K})", - localizedKeyPath, @"name_zh-CN", @"name_zh", @"name"]; + return [NSExpression expressionForFunctionHelper:@"mgl_coalesce:" arguments:@[[NSExpression expressionForConstantValue:@[ + [NSExpression expressionForKeyPath:localizedKeyPath], + [NSExpression expressionForKeyPath:@"name_zh-CN"], + [NSExpression expressionForKeyPath:@"name_zh"], + [NSExpression expressionForKeyPath:@"name"], + ]]]]; } // Mapbox Streets v8 has `name_zh-Hant`, we should fallback to Simplified Chinese if the field has no value. if ([localizedKeyPath isEqualToString:@"name_zh-Hant"]) { - return [NSExpression expressionWithFormat:@"mgl_coalesce({%K, %K, %K, %K, %K})", - localizedKeyPath, @"name_zh-Hans", @"name_zh-CN", @"name_zh", @"name"]; + return [NSExpression expressionForFunctionHelper:@"mgl_coalesce:" arguments:@[[NSExpression expressionForConstantValue:@[ + [NSExpression expressionForKeyPath:localizedKeyPath], + [NSExpression expressionForKeyPath:@"name_zh-CN"], + [NSExpression expressionForKeyPath:@"name_zh"], + [NSExpression expressionForKeyPath:@"name"], + ]]]]; } // Other keypath fallback to `name` - return [NSExpression expressionWithFormat:@"mgl_coalesce({%K, %K})", localizedKeyPath, @"name"]; + return [NSExpression expressionForFunctionHelper:@"mgl_coalesce:" arguments:@[[NSExpression expressionForConstantValue:@[ + [NSExpression expressionForKeyPath:localizedKeyPath], + [NSExpression expressionForKeyPath:@"name"], + ]]]]; } return self; } diff --git a/platform/darwin/test/MLNDocumentationGuideTests.swift b/platform/darwin/test/MLNDocumentationGuideTests.swift index 4df6cda07..71a44bbb3 100644 --- a/platform/darwin/test/MLNDocumentationGuideTests.swift +++ b/platform/darwin/test/MLNDocumentationGuideTests.swift @@ -266,7 +266,6 @@ class MLNDocumentationGuideTests: XCTestCase, MLNMapViewDelegate { let red = NSExpression(forConstantValue: UIColor.red) let yellow = NSExpression(forConstantValue: UIColor.yellow) - XCTExpectFailure("Awaiting unit test refactoring for https://github.com/maplibre/maplibre-native/issues/331") layer.circleColor = NSExpression(forMLNMatchingKey: type, in: [earthquake: orange, explosion: red, quarryBlast: yellow], default: defaultColor) diff --git a/platform/darwin/test/MLNExpressionTests.mm b/platform/darwin/test/MLNExpressionTests.mm index a9390d718..de86cbd29 100644 --- a/platform/darwin/test/MLNExpressionTests.mm +++ b/platform/darwin/test/MLNExpressionTests.mm @@ -1526,9 +1526,6 @@ using namespace std::string_literals; XCTAssertEqualObjects([NSExpression expressionWithMLNJSONObject:jsonExpression], expression); } { - #if TARGET_OS_IPHONE - XCTExpectFailure(@"Awaiting unit test refactoring for https://github.com/maplibre/maplibre-native/issues/331"); - #endif NSExpression *expression = [[NSExpression expressionForConstantValue:@"Old"] mgl_expressionByAppendingExpression:[NSExpression expressionForConstantValue:@"MacDonald"]]; NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"]; diff --git a/platform/darwin/test/MLNMapCameraTests.m b/platform/darwin/test/MLNMapCameraTests.m index 7afb97b26..d38aadc63 100644 --- a/platform/darwin/test/MLNMapCameraTests.m +++ b/platform/darwin/test/MLNMapCameraTests.m @@ -27,9 +27,9 @@ XCTAssertEqual(camera.altitude, mkCamera.altitude, @"Eye altitude in untilted camera should match MapKit."); XCTAssertEqual(camera.pitch, 0, @"Camera directly over center coordinate should be untilted."); XCTAssertEqual(camera.pitch, mkCamera.pitch, @"Camera directly over center coordinate should have same pitch as MapKit."); - // https://github.com/maplibre/maplibre-native/issues/1303 - // XCTAssertEqual(camera.heading, 0, @"Camera directly over center coordinate should be unrotated."); - // XCTAssertEqual(camera.heading, mkCamera.heading, @"Camera directly over center coordinate should have same heading as MapKit."); + + XCTAssertEqual(camera.heading, 0, @"Camera directly over center coordinate should be unrotated."); + XCTAssertEqual(camera.heading, mkCamera.heading, @"Camera directly over center coordinate should have same heading as MapKit."); camera = [MLNMapCamera cameraLookingAtCenterCoordinate:fountainSquare fromEyeCoordinate:unionTerminal diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 7bbe3c1bb..f6fad861c 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -998,6 +998,8 @@ public: _mbglView.reset(); _rendererFrontend.reset(); + + _style = nil; } - (void)dealloc