Port several iOS fixes from GrabMaps (#4023)

This commit is contained in:
Wei Chen
2026-01-08 19:53:09 +08:00
committed by GitHub
parent 32eed7a806
commit 7e3544f8df
16 changed files with 136 additions and 64 deletions

View File

@@ -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<double>)geometryObject {
return mbgl::EmptyGeometry();
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; identifier = %@, attributes = %@>",

View File

@@ -53,15 +53,20 @@ NSDictionary<NSString *, id> *NSDictionaryFeatureForGeometry(NSDictionary *geome
NS_ASSUME_NONNULL_END
#define MLN_DEFINE_FEATURE_INIT_WITH_CODER() \
-(instancetype)initWithCoder : (NSCoder *)decoder { \
if (self = [super initWithCoder:decoder]) { \
NSSet<Class> *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<Class> *identifierClasses = \
[NSSet setWithArray:@[ [NSString class], [NSNumber class] ]]; \
identifier = [decoder decodeObjectOfClasses:identifierClasses forKey:@"identifier"]; \
NSSet<Class> *attributesClasses = \
[NSSet setWithArray:@[ [NSDictionary class], [NSArray class] ]]; \
_attributes = [decoder decodeObjectOfClasses:attributesClasses forKey:@"attributes"]; \
} \
return self; \
} \
+(BOOL)supportsSecureCoding { \
return YES; \
}
#define MLN_DEFINE_FEATURE_ENCODE() \

View File

@@ -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<double, 16> array) {
};
return mat4;
}
BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
{
return MAX(left, right) - MIN(left, right) <= accuracy;
}

View File

@@ -151,3 +151,5 @@ CLLocationDirection MLNDirectionBetweenCoordinates(CLLocationCoordinate2D firstC
CGPoint MLNPointRounded(CGPoint point);
MLNMatrix4 MLNMatrix4Make(std::array<double, 16> mat);
FOUNDATION_EXTERN BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy);

View File

@@ -6,11 +6,6 @@
#include <mbgl/math/wrap.hpp>
BOOL MLNEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
{
return MAX(left, right) - MIN(left, right) <= accuracy;
}
@implementation MLNMapCamera
+ (BOOL)supportsSecureCoding

View File

@@ -28,6 +28,10 @@
return self;
}
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
MLNLogInfo(@"Initializing with coder.");

View File

@@ -14,6 +14,10 @@ NS_ASSUME_NONNULL_BEGIN
std::vector<CLLocationCoordinate2D> _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<Class> *coordinatesClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class]]];
NSArray *coordinates = [decoder decodeObjectOfClasses:coordinatesClasses forKey:@"coordinates"];
_coordinates = [coordinates mgl_coordinates];
}
return self;

View File

@@ -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<Class> *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<MLNPolygon *> *)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<Class> *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;
}

View File

@@ -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<Class> *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;
}

View File

@@ -8,6 +8,10 @@
@implementation MLNShapeCollection
+ (BOOL)supportsSecureCoding {
return YES;
}
+ (instancetype)shapeCollectionWithShapes:(NSArray<MLNShape *> *)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<Class> *shapeClasses = [NSSet setWithArray:@[[NSDictionary class], [NSArray class], [MLNShape class]]];
_shapes = [decoder decodeObjectOfClasses:shapeClasses forKey:@"shapes"];
}
return self;
}

View File

@@ -10,7 +10,8 @@
}
- (std::vector<CLLocationCoordinate2D>)mgl_decodeLocationCoordinates2DForKey:(NSString *)key {
NSArray *coordinates = [self decodeObjectOfClass:[NSArray class] forKey:key];
NSSet<Class> *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]);
}

View File

@@ -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<NSExpression *, NSExpression *> *)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<NSExpression *> *)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<NSString *, NSString *> *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<NSNumber *, NSExpression *> *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;
}

View File

@@ -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)

View File

@@ -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"];

View File

@@ -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

View File

@@ -998,6 +998,8 @@ public:
_mbglView.reset();
_rendererFrontend.reset();
_style = nil;
}
- (void)dealloc