[ios, macos] features and annotations now conforms to NSSecureCoding
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#import "MGLPolyline+MGLAdditions.h"
|
||||
#import "MGLPolygon+MGLAdditions.h"
|
||||
#import "NSDictionary+MGLAdditions.h"
|
||||
#import "NSArray+MGLAdditions.h"
|
||||
|
||||
#import "NSExpression+MGLAdditions.h"
|
||||
|
||||
@@ -25,6 +26,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -47,6 +52,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -69,6 +78,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -91,6 +104,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -113,6 +130,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -135,6 +156,10 @@
|
||||
@synthesize identifier;
|
||||
@synthesize attributes;
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
@@ -163,6 +188,10 @@
|
||||
return [super shapeCollectionWithShapes:shapes];
|
||||
}
|
||||
|
||||
MGL_DEFINE_FEATURE_INIT_WITH_CODER();
|
||||
MGL_DEFINE_FEATURE_ENCODE();
|
||||
MGL_DEFINE_FEATURE_IS_EQUAL();
|
||||
|
||||
- (id)attributeForKey:(NSString *)key {
|
||||
return self.attributes[key];
|
||||
}
|
||||
|
||||
@@ -37,3 +37,31 @@ mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *at
|
||||
NS_DICTIONARY_OF(NSString *, id) *NSDictionaryFeatureForGeometry(NSDictionary *geometry, NSDictionary *attributes, id identifier);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#define MGL_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 MGL_DEFINE_FEATURE_ENCODE() \
|
||||
- (void)encodeWithCoder:(NSCoder *)coder { \
|
||||
[super encodeWithCoder:coder]; \
|
||||
[coder encodeObject:identifier forKey:@"identifier"]; \
|
||||
[coder encodeObject:attributes forKey:@"attributes"]; \
|
||||
}
|
||||
|
||||
#define MGL_DEFINE_FEATURE_IS_EQUAL() \
|
||||
- (BOOL)isEqual:(id)other { \
|
||||
if (other == self) return YES; \
|
||||
if (![other isKindOfClass:[self class]]) return NO; \
|
||||
__typeof(self) otherFeature = other; \
|
||||
return [super isEqual:other] && [self geoJSONObject] == [otherFeature geoJSONObject]; \
|
||||
} \
|
||||
- (NSUInteger)hash { \
|
||||
return [super hash] + [[self geoJSONDictionary] hash]; \
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#import "MGLMultiPoint_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "MGLShape_Private.h"
|
||||
#import "NSCoder+MGLAdditions.h"
|
||||
#import "MGLTypes.h"
|
||||
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
@implementation MGLMultiPoint
|
||||
{
|
||||
mbgl::optional<mbgl::LatLngBounds> _bounds;
|
||||
@@ -27,6 +26,39 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
_coordinates = [decoder mgl_decodeLocationCoordinates2DForKey:@"coordinates"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[super encodeWithCoder:coder];
|
||||
[coder mgl_encodeLocationCoordinates2D:_coordinates forKey:@"coordinates"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLMultiPoint class]]) return NO;
|
||||
|
||||
MGLMultiPoint *otherMultipoint = other;
|
||||
return ([super isEqual:otherMultipoint]
|
||||
&& _coordinates == otherMultipoint->_coordinates);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
NSUInteger hash = [super hash];
|
||||
for (auto coord : _coordinates) {
|
||||
hash += @(coord.latitude+coord.longitude).hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)coordinate
|
||||
{
|
||||
NSAssert([self pointCount] > 0, @"A multipoint must have coordinates");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#import "MGLPointAnnotation.h"
|
||||
|
||||
#import "MGLShape_Private.h"
|
||||
#import "NSCoder+MGLAdditions.h"
|
||||
|
||||
#import <mbgl/util/geometry.hpp>
|
||||
|
||||
@@ -9,6 +10,41 @@
|
||||
|
||||
@synthesize coordinate;
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
if (self = [super initWithCoder:coder]) {
|
||||
self.coordinate = [coder decodeMGLCoordinateForKey:@"coordinate"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeMGLCoordinate:coordinate forKey:@"coordinate"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if (other == self) return YES;
|
||||
if (![other isKindOfClass:[MGLPointAnnotation class]]) return NO;
|
||||
|
||||
MGLPointAnnotation *otherAnnotation = other;
|
||||
return ([super isEqual:other]
|
||||
&& self.coordinate.latitude == otherAnnotation.coordinate.latitude
|
||||
&& self.coordinate.longitude == otherAnnotation.coordinate.longitude);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
return [super hash] + @(self.coordinate.latitude).hash + @(self.coordinate.longitude).hash;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p; title = %@; subtitle = %@; coordinate = %f, %f>",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#import "MGLPointCollection_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "NSArray+MGLAdditions.h"
|
||||
|
||||
#import <mbgl/util/geojson.hpp>
|
||||
#import <mbgl/util/geometry.hpp>
|
||||
@@ -8,12 +9,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation MGLPointCollection
|
||||
{
|
||||
MGLCoordinateBounds _overlayBounds;
|
||||
mbgl::optional<mbgl::LatLngBounds> _bounds;
|
||||
std::vector<CLLocationCoordinate2D> _coordinates;
|
||||
}
|
||||
|
||||
@synthesize overlayBounds = _overlayBounds;
|
||||
|
||||
+ (instancetype)pointCollectionWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count
|
||||
{
|
||||
return [[self alloc] initWithCoordinates:coords count:count];
|
||||
@@ -25,16 +24,43 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (self)
|
||||
{
|
||||
_coordinates = { coords, coords + count };
|
||||
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
|
||||
for (auto coordinate : _coordinates)
|
||||
{
|
||||
bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
|
||||
}
|
||||
_overlayBounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
NSArray *coordinates = [decoder decodeObjectOfClass:[NSArray class] forKey:@"coordinates"];
|
||||
_coordinates = [coordinates mgl_coordinates];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:[NSArray mgl_coordinatesFromCoordinates:_coordinates] forKey:@"coordinates"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLPointCollection class]]) return NO;
|
||||
|
||||
MGLPointCollection *otherCollection = (MGLPointCollection *)other;
|
||||
return ([super isEqual:other]
|
||||
&& ((![self geoJSONDictionary] && ![otherCollection geoJSONDictionary]) || [[self geoJSONDictionary] isEqualToDictionary:[otherCollection geoJSONDictionary]]));
|
||||
}
|
||||
|
||||
- (MGLCoordinateBounds)overlayBounds {
|
||||
if (!_bounds) {
|
||||
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
|
||||
for (auto coordinate : _coordinates) {
|
||||
bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
|
||||
}
|
||||
_bounds = bounds;
|
||||
}
|
||||
return MGLCoordinateBoundsFromLatLngBounds(*_bounds);
|
||||
}
|
||||
|
||||
- (NSUInteger)pointCount
|
||||
{
|
||||
return _coordinates.size();
|
||||
@@ -65,7 +91,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds
|
||||
{
|
||||
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
|
||||
return MGLCoordinateBoundsIntersectsCoordinateBounds(self.overlayBounds, overlayBounds);
|
||||
}
|
||||
|
||||
- (mbgl::Geometry<double>)geometryObject
|
||||
|
||||
@@ -28,6 +28,32 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
self = [super initWithCoder:decoder];
|
||||
if (self) {
|
||||
_interiorPolygons = [decoder decodeObjectOfClass:[NSArray class] forKey:@"interiorPolygons"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:self.interiorPolygons forKey:@"interiorPolygons"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLPolygon class]]) return NO;
|
||||
|
||||
MGLPolygon *otherPolygon = (MGLPolygon *)other;
|
||||
return ([super isEqual:otherPolygon] &&
|
||||
[[self geoJSONDictionary] isEqualToDictionary:[otherPolygon geoJSONDictionary]]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [super hash] + [[self geoJSONDictionary] hash];
|
||||
}
|
||||
|
||||
- (mbgl::LinearRing<double>)ring {
|
||||
NSUInteger count = self.pointCount;
|
||||
CLLocationCoordinate2D *coordinates = self.coordinates;
|
||||
@@ -100,6 +126,35 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
_polygons = [decoder decodeObjectOfClass:[NSArray class] forKey:@"polygons"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:_polygons forKey:@"polygons"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLMultiPolygon class]]) return NO;
|
||||
|
||||
MGLMultiPolygon *otherMultiPolygon = other;
|
||||
return [super isEqual:other]
|
||||
&& [self.polygons isEqualToArray:otherMultiPolygon.polygons];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [super hash];
|
||||
for (MGLPolygon *polygon in self.polygons) {
|
||||
hash += [polygon hash];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
|
||||
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,36 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
_polylines = [decoder decodeObjectOfClass:[NSArray class] forKey:@"polylines"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:_polylines forKey:@"polylines"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLMultiPolyline class]]) return NO;
|
||||
|
||||
MGLMultiPolyline *otherMultipoline = other;
|
||||
return ([super isEqual:otherMultipoline]
|
||||
&& [self.polylines isEqualToArray:otherMultipoline.polylines]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [super hash];
|
||||
for (MGLPolyline *polyline in self.polylines) {
|
||||
hash += [polyline hash];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
|
||||
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
you can add some kinds of shapes directly to a map view as annotations or
|
||||
overlays.
|
||||
*/
|
||||
@interface MGLShape : NSObject <MGLAnnotation>
|
||||
@interface MGLShape : NSObject <MGLAnnotation, NSSecureCoding>
|
||||
|
||||
#pragma mark Creating a Shape
|
||||
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
#import "MGLFeature_Private.h"
|
||||
|
||||
#import "NSString+MGLAdditions.h"
|
||||
#import "MGLTypes.h"
|
||||
|
||||
#import <mbgl/util/geo.hpp>
|
||||
|
||||
bool operator==(const CLLocationCoordinate2D lhs, const CLLocationCoordinate2D rhs) {
|
||||
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude;
|
||||
}
|
||||
|
||||
@implementation MGLShape
|
||||
|
||||
+ (nullable MGLShape *)shapeWithData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError * _Nullable *)outError {
|
||||
@@ -42,10 +51,63 @@
|
||||
return [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)coordinate {
|
||||
[NSException raise:@"MGLAbstractClassException"
|
||||
format:@"MGLShape is an abstract class"];
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_title = [coder decodeObjectOfClass:[NSString class] forKey:@"title"];
|
||||
_subtitle = [coder decodeObjectOfClass:[NSString class] forKey:@"subtitle"];
|
||||
#if !TARGET_OS_IPHONE
|
||||
_toolTip = [coder decodeObjectOfClass:[NSString class] forKey:@"toolTip"];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[coder encodeObject:_title forKey:@"title"];
|
||||
[coder encodeObject:_subtitle forKey:@"subtitle"];
|
||||
#if !TARGET_OS_IPHONE
|
||||
[coder encodeObject:_toolTip forKey:@"toolTip"];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other
|
||||
{
|
||||
if (other == self) { return YES; }
|
||||
id <MGLAnnotation> annotation = other;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
return ((!_title && ![annotation title]) || [_title isEqualToString:[annotation title]])
|
||||
&& ((!_subtitle && ![annotation subtitle]) || [_subtitle isEqualToString:[annotation subtitle]]);
|
||||
#else
|
||||
return ((!_title && ![annotation title]) || [_title isEqualToString:[annotation title]])
|
||||
&& ((!_subtitle && ![annotation subtitle]) || [_subtitle isEqualToString:[annotation subtitle]])
|
||||
&& ((!_toolTip && ![annotation toolTip]) || [_toolTip isEqualToString:[annotation toolTip]]);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
NSUInteger hash;
|
||||
hash += _title.hash;
|
||||
hash += _subtitle.hash;
|
||||
#if !TARGET_OS_IPHONE
|
||||
hash += _toolTip.hash;
|
||||
#endif
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)coordinate
|
||||
{
|
||||
[[NSException exceptionWithName:@"MGLAbstractClassException"
|
||||
reason:@"MGLShape is an abstract class"
|
||||
userInfo:nil] raise];
|
||||
return kCLLocationCoordinate2DInvalid;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,35 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
_shapes = [decoder decodeObjectOfClass:[NSArray class] forKey:@"shapes"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:_shapes forKey:@"shapes"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLShapeCollection class]]) return NO;
|
||||
|
||||
MGLShapeCollection *otherShapeCollection = other;
|
||||
return [super isEqual:otherShapeCollection]
|
||||
&& [_shapes isEqualToArray:otherShapeCollection.shapes];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [super hash];
|
||||
for (MGLShape *shape in _shapes) {
|
||||
hash += [shape hash];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)coordinate {
|
||||
return _shapes.firstObject.coordinate;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#import <mbgl/util/geojson.hpp>
|
||||
#import <mbgl/util/geometry.hpp>
|
||||
#import <mbgl/util/geo.hpp>
|
||||
|
||||
bool operator==(const CLLocationCoordinate2D lhs, const CLLocationCoordinate2D rhs);
|
||||
|
||||
@interface MGLShape (Private)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#import <mbgl/util/feature.hpp>
|
||||
|
||||
@@ -9,4 +10,18 @@
|
||||
/** Returns a string resulting from inserting a separator between each attributed string in the array */
|
||||
- (NSAttributedString *)mgl_attributedComponentsJoinedByString:(NSString *)separator;
|
||||
|
||||
/**
|
||||
Converts std::vector<CLLocationCoordinate> into an NSArray containing dictionary
|
||||
representations of coordinates with the following structure:
|
||||
[{"latitude": lat, "longitude": lng}]
|
||||
*/
|
||||
+ (NSArray *)mgl_coordinatesFromCoordinates:(std::vector<CLLocationCoordinate2D>)coords;
|
||||
|
||||
/**
|
||||
Converts the receiver into a std::vector<CLLocationCoordinate>.
|
||||
Receiver must conform to the following structure:
|
||||
[{"latitude": lat, "longitude": lng}]
|
||||
*/
|
||||
- (std::vector<CLLocationCoordinate2D>)mgl_coordinates;
|
||||
|
||||
@end
|
||||
|
||||
@@ -38,4 +38,28 @@
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
+ (NSArray *)mgl_coordinatesFromCoordinates:(std::vector<CLLocationCoordinate2D>)coords {
|
||||
NSMutableArray *coordinates = [NSMutableArray array];
|
||||
for (auto coord : coords) {
|
||||
[coordinates addObject:@{@"latitude": @(coord.latitude),
|
||||
@"longitude": @(coord.longitude)}];
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
- (std::vector<CLLocationCoordinate2D>)mgl_coordinates {
|
||||
NSUInteger numberOfCoordinates = [self count];
|
||||
CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(numberOfCoordinates * sizeof(CLLocationCoordinate2D));
|
||||
|
||||
for (NSUInteger i = 0; i < numberOfCoordinates; i++) {
|
||||
coords[i] = CLLocationCoordinate2DMake([self[i][@"latitude"] doubleValue],
|
||||
[self[i][@"longitude"] doubleValue]);
|
||||
}
|
||||
|
||||
std::vector<CLLocationCoordinate2D> coordinates = { coords, coords + numberOfCoordinates };
|
||||
free(coords);
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
16
platform/darwin/src/NSCoder+MGLAdditions.h
Normal file
16
platform/darwin/src/NSCoder+MGLAdditions.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#import <mbgl/util/feature.hpp>
|
||||
|
||||
@interface NSCoder (MGLAdditions)
|
||||
|
||||
- (void)encodeMGLCoordinate:(CLLocationCoordinate2D)coordinate forKey:(NSString *)key;
|
||||
|
||||
- (CLLocationCoordinate2D)decodeMGLCoordinateForKey:(NSString *)key;
|
||||
|
||||
- (void)mgl_encodeLocationCoordinates2D:(std::vector<CLLocationCoordinate2D>)coordinates forKey:(NSString *)key;
|
||||
|
||||
- (std::vector<CLLocationCoordinate2D>)mgl_decodeLocationCoordinates2DForKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
26
platform/darwin/src/NSCoder+MGLAdditions.mm
Normal file
26
platform/darwin/src/NSCoder+MGLAdditions.mm
Normal file
@@ -0,0 +1,26 @@
|
||||
#import "NSCoder+MGLAdditions.h"
|
||||
|
||||
#import "NSArray+MGLAdditions.h"
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
|
||||
@implementation NSCoder (MGLAdditions)
|
||||
|
||||
- (void)mgl_encodeLocationCoordinates2D:(std::vector<CLLocationCoordinate2D>)coordinates forKey:(NSString *)key {
|
||||
[self encodeObject:[NSArray mgl_coordinatesFromCoordinates:coordinates] forKey:key];
|
||||
}
|
||||
|
||||
- (std::vector<CLLocationCoordinate2D>)mgl_decodeLocationCoordinates2DForKey:(NSString *)key {
|
||||
NSArray *coordinates = [self decodeObjectOfClass:[NSArray class] forKey:key];
|
||||
return [coordinates mgl_coordinates];
|
||||
}
|
||||
|
||||
- (void)encodeMGLCoordinate:(CLLocationCoordinate2D)coordinate forKey:(NSString *)key {
|
||||
[self encodeObject:@{@"latitude": @(coordinate.latitude), @"longitude": @(coordinate.longitude)} forKey:key];
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)decodeMGLCoordinateForKey:(NSString *)key {
|
||||
NSDictionary *coordinate = [self decodeObjectForKey:key];
|
||||
return CLLocationCoordinate2DMake([coordinate[@"latitude"] doubleValue], [coordinate[@"longitude"] doubleValue]);
|
||||
}
|
||||
|
||||
@end
|
||||
469
platform/darwin/test/MGLCodingTests.m
Normal file
469
platform/darwin/test/MGLCodingTests.m
Normal file
@@ -0,0 +1,469 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#import "MGLUserLocation_Private.h"
|
||||
#endif
|
||||
|
||||
@interface MGLCodingTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation MGLCodingTests
|
||||
|
||||
- (NSString *)temporaryFilePathForClass:(Class)clazz {
|
||||
return [NSTemporaryDirectory() stringByAppendingPathComponent:NSStringFromClass(clazz)];
|
||||
}
|
||||
|
||||
- (void)testPointAnnotation {
|
||||
MGLPointAnnotation *annotation = [[MGLPointAnnotation alloc] init];
|
||||
annotation.coordinate = CLLocationCoordinate2DMake(0.5, 0.5);
|
||||
annotation.title = @"title";
|
||||
annotation.subtitle = @"subtitle";
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:MGLPointAnnotation.class];
|
||||
[NSKeyedArchiver archiveRootObject:annotation toFile:filePath];
|
||||
MGLPointAnnotation *unarchivedAnnotation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(annotation, unarchivedAnnotation);
|
||||
}
|
||||
|
||||
- (void)testPointFeature {
|
||||
MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init];
|
||||
pointFeature.title = @"title";
|
||||
pointFeature.subtitle = @"subtitle";
|
||||
pointFeature.identifier = @(123);
|
||||
pointFeature.attributes = @{@"bbox": @[@1, @2, @3, @4]};
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class];
|
||||
[NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath];
|
||||
MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(pointFeature, unarchivedPointFeature);
|
||||
}
|
||||
|
||||
- (void)testPolyline {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0.129631234123, 1.7812739312551),
|
||||
CLLocationCoordinate2DMake(2.532083092342, 3.5216418292392)
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
polyline.title = @"title";
|
||||
polyline.subtitle = @"subtitle";
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPolyline class]];
|
||||
[NSKeyedArchiver archiveRootObject:polyline toFile:filePath];
|
||||
MGLPolyline *unarchivedPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(polyline, unarchivedPolyline);
|
||||
|
||||
CLLocationCoordinate2D otherCoordinates[] = {
|
||||
CLLocationCoordinate2DMake(-1, -2)
|
||||
};
|
||||
|
||||
[unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates];
|
||||
|
||||
XCTAssertNotEqualObjects(polyline, unarchivedPolyline);
|
||||
}
|
||||
|
||||
- (void)testPolygon {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0.664482398, 1.8865675),
|
||||
CLLocationCoordinate2DMake(2.13224687, 3.9984632)
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
polygon.title = nil;
|
||||
polygon.subtitle = @"subtitle";
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]];
|
||||
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
|
||||
|
||||
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(polygon, unarchivedPolygon);
|
||||
}
|
||||
|
||||
- (void)testPolygonWithInteriorPolygons {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 20)
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
CLLocationCoordinate2D interiorCoordinates[] = {
|
||||
CLLocationCoordinate2DMake(4, 4),
|
||||
CLLocationCoordinate2DMake(6, 6)
|
||||
};
|
||||
|
||||
NSUInteger numberOfInteriorCoordinates = sizeof(interiorCoordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPolygon *interiorPolygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:numberOfInteriorCoordinates];
|
||||
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates interiorPolygons:@[interiorPolygon]];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]];
|
||||
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
|
||||
|
||||
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(polygon, unarchivedPolygon);
|
||||
}
|
||||
|
||||
- (void)testPolylineFeature {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 20)
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
polylineFeature.attributes = @{@"bbox": @[@0, @1, @2, @3]};
|
||||
polylineFeature.identifier = @"identifier";
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPolylineFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:polylineFeature toFile:filePath];
|
||||
|
||||
MGLPolylineFeature *unarchivedPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(polylineFeature, unarchivedPolylineFeature);
|
||||
|
||||
unarchivedPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]};
|
||||
|
||||
XCTAssertNotEqualObjects(polylineFeature, unarchivedPolylineFeature);
|
||||
}
|
||||
|
||||
- (void)testPolygonFeature {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 20)
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygonFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:polygonFeature toFile:filePath];
|
||||
|
||||
MGLPolygonFeature *unarchivedPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(polygonFeature, unarchivedPolygonFeature);
|
||||
|
||||
unarchivedPolygonFeature.identifier = @"test";
|
||||
|
||||
XCTAssertNotEqualObjects(polygonFeature, unarchivedPolygonFeature);
|
||||
}
|
||||
|
||||
- (void)testPointCollection {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 11),
|
||||
CLLocationCoordinate2DMake(20, 21),
|
||||
CLLocationCoordinate2DMake(30, 31),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPointCollection *pointCollection = [MGLPointCollection pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollection class]];
|
||||
[NSKeyedArchiver archiveRootObject:pointCollection toFile:filePath];
|
||||
|
||||
MGLPointCollection *unarchivedPointCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(pointCollection, unarchivedPointCollection);
|
||||
}
|
||||
|
||||
- (void)testPointCollectionFeature {
|
||||
NSMutableArray *features = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < 100; i++) {
|
||||
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
|
||||
feature.coordinate = CLLocationCoordinate2DMake(arc4random() % 90, arc4random() % 180);
|
||||
[features addObject:feature];
|
||||
}
|
||||
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 11),
|
||||
CLLocationCoordinate2DMake(20, 21),
|
||||
CLLocationCoordinate2DMake(30, 31),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPointCollectionFeature *collection = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
collection.identifier = @"identifier";
|
||||
collection.attributes = @{@"bbox": @[@1, @2, @3, @4]};
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollectionFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:collection toFile:filePath];
|
||||
|
||||
MGLPointCollectionFeature *unarchivedCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(collection, unarchivedCollection);
|
||||
|
||||
unarchivedCollection.identifier = @"newIdentifier";
|
||||
|
||||
XCTAssertNotEqualObjects(collection, unarchivedCollection);
|
||||
}
|
||||
|
||||
- (void)testMultiPolyline {
|
||||
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 11),
|
||||
CLLocationCoordinate2DMake(20, 21),
|
||||
CLLocationCoordinate2DMake(30, 31),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
NSMutableArray *polylines = [NSMutableArray array];
|
||||
|
||||
for (NSUInteger i = 0; i < 100; i++) {
|
||||
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
[polylines addObject:polyline];
|
||||
}
|
||||
|
||||
MGLMultiPolyline *multiPolyline = [MGLMultiPolyline multiPolylineWithPolylines:polylines];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolyline class]];
|
||||
[NSKeyedArchiver archiveRootObject:multiPolyline toFile:filePath];
|
||||
|
||||
MGLMultiPolyline *unarchivedMultiPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
MGLMultiPolyline *anotherMultipolyline = [MGLMultiPolyline multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]];
|
||||
|
||||
XCTAssertEqualObjects(multiPolyline, unarchivedMultiPolyline);
|
||||
XCTAssertNotEqualObjects(unarchivedMultiPolyline, anotherMultipolyline);
|
||||
}
|
||||
|
||||
- (void)testMultiPolygon {
|
||||
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(0, 1),
|
||||
CLLocationCoordinate2DMake(10, 11),
|
||||
CLLocationCoordinate2DMake(20, 21),
|
||||
CLLocationCoordinate2DMake(30, 31),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
NSMutableArray *polygons = [NSMutableArray array];
|
||||
|
||||
for (NSUInteger i = 0; i < 100; i++) {
|
||||
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
[polygons addObject:polygon];
|
||||
}
|
||||
|
||||
MGLMultiPolygon *multiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:polygons];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolygon class]];
|
||||
[NSKeyedArchiver archiveRootObject:multiPolygon toFile:filePath];
|
||||
|
||||
MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
|
||||
|
||||
XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon);
|
||||
XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon);
|
||||
}
|
||||
|
||||
- (void)testShapeCollection {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(10.12315786, 11.23451186),
|
||||
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
|
||||
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
|
||||
MGLShapeCollection *shapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polyline, polygon]];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollection class]];
|
||||
[NSKeyedArchiver archiveRootObject:shapeCollection toFile:filePath];
|
||||
|
||||
MGLShapeCollection *unarchivedShapeCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
MGLShapeCollection *anotherShapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polygon]];
|
||||
|
||||
XCTAssertEqualObjects(shapeCollection, unarchivedShapeCollection);
|
||||
XCTAssertNotEqualObjects(shapeCollection, anotherShapeCollection);
|
||||
}
|
||||
|
||||
- (void)testMultiPolylineFeature {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(10.12315786, 11.23451186),
|
||||
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
|
||||
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
NSMutableArray *polylines = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < 100; i++) {
|
||||
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
polylineFeature.identifier = @(arc4random() % 100).stringValue;
|
||||
[polylines addObject:polylineFeature];
|
||||
}
|
||||
|
||||
MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
|
||||
multiPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]};
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:multiPolylineFeature toFile:filePath];
|
||||
|
||||
MGLMultiPolylineFeature *unarchivedMultiPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
MGLMultiPolylineFeature *anotherMultiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]];
|
||||
|
||||
XCTAssertEqualObjects(multiPolylineFeature, unarchivedMultiPolylineFeature);
|
||||
XCTAssertNotEqualObjects(unarchivedMultiPolylineFeature, anotherMultiPolylineFeature);
|
||||
}
|
||||
|
||||
- (void)testMultiPolygonFeature {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(10.12315786, 11.23451185),
|
||||
CLLocationCoordinate2DMake(20.88471238, 21.93684215),
|
||||
CLLocationCoordinate2DMake(30.15697236, 31.32988123),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
NSMutableArray *polygons = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < 100; i++ ) {
|
||||
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
polygonFeature.identifier = @(arc4random_uniform(100)).stringValue;
|
||||
[polygons addObject:polygonFeature];
|
||||
}
|
||||
|
||||
MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
|
||||
multiPolygonFeature.attributes = @{@"bbox": @[@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100))]};
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:multiPolygonFeature toFile:filePath];
|
||||
|
||||
MGLMultiPolygonFeature *unarchivedMultiPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
MGLMultiPolygonFeature *anotherMultiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
|
||||
|
||||
XCTAssertEqualObjects(multiPolygonFeature, unarchivedMultiPolygonFeature);
|
||||
XCTAssertNotEqualObjects(anotherMultiPolygonFeature, unarchivedMultiPolygonFeature);
|
||||
}
|
||||
|
||||
- (void)testShapeCollectionFeature {
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
CLLocationCoordinate2DMake(10.12315786, 11.23451186),
|
||||
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
|
||||
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
|
||||
};
|
||||
|
||||
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
|
||||
|
||||
MGLPolylineFeature *polyline = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
MGLPolygonFeature *polygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
|
||||
|
||||
MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polyline, polygon]];
|
||||
shapeCollectionFeature.identifier = @(arc4random_uniform(100)).stringValue;
|
||||
shapeCollectionFeature.attributes = @{@"bbox":@[@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100)),
|
||||
@(arc4random_uniform(100))]};
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollectionFeature class]];
|
||||
[NSKeyedArchiver archiveRootObject:shapeCollectionFeature toFile:filePath];
|
||||
|
||||
MGLShapeCollectionFeature *unarchivedShapeCollectionFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(shapeCollectionFeature, unarchivedShapeCollectionFeature);
|
||||
}
|
||||
|
||||
- (void)testAnnotationImage {
|
||||
#if TARGET_OS_IPHONE
|
||||
UIGraphicsBeginImageContext(CGSizeMake(10, 10));
|
||||
[[UIColor redColor] setFill];
|
||||
UIRectFill(CGRectMake(0, 0, 10, 10));
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
#else
|
||||
NSImage *image = [[NSImage alloc] initWithSize:CGSizeMake(10, 10)];
|
||||
[image lockFocus];
|
||||
[[NSColor redColor] drawSwatchInRect:CGRectMake(0, 0, 10, 10)];
|
||||
[image unlockFocus];
|
||||
#endif
|
||||
|
||||
MGLAnnotationImage *annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@(arc4random_uniform(100)).stringValue];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationImage class]];
|
||||
[NSKeyedArchiver archiveRootObject:annotationImage toFile:filePath];
|
||||
|
||||
MGLAnnotationImage *unarchivedAnnotationImage = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(annotationImage, unarchivedAnnotationImage);
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (void)testAnnotationView {
|
||||
MGLAnnotationView *annotationView = [[MGLAnnotationView alloc] initWithReuseIdentifier:@"id"];
|
||||
annotationView.enabled = NO;
|
||||
annotationView.selected = YES;
|
||||
annotationView.draggable = YES;
|
||||
annotationView.centerOffset = CGVectorMake(10, 10);
|
||||
annotationView.scalesWithViewingDistance = NO;
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationView class]];
|
||||
[NSKeyedArchiver archiveRootObject:annotationView toFile:filePath];
|
||||
|
||||
MGLAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled);
|
||||
XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected);
|
||||
XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable);
|
||||
XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset));
|
||||
XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (void)testUserLocation {
|
||||
MGLUserLocation *userLocation = [[MGLUserLocation alloc] init];
|
||||
userLocation.location = [[CLLocation alloc] initWithLatitude:1 longitude:1];
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocation class]];
|
||||
[NSKeyedArchiver archiveRootObject:userLocation toFile:filePath];
|
||||
|
||||
MGLUserLocation *unarchivedUserLocation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqualObjects(userLocation, unarchivedUserLocation);
|
||||
unarchivedUserLocation.location = [[CLLocation alloc] initWithLatitude:10 longitude:10];
|
||||
XCTAssertNotEqualObjects(userLocation, unarchivedUserLocation);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (void)testUserLocationAnnotationView {
|
||||
MGLUserLocationAnnotationView *annotationView = [[MGLUserLocationAnnotationView alloc] init];
|
||||
annotationView.enabled = NO;
|
||||
annotationView.selected = YES;
|
||||
annotationView.draggable = YES;
|
||||
annotationView.centerOffset = CGVectorMake(10, 10);
|
||||
annotationView.scalesWithViewingDistance = NO;
|
||||
|
||||
NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocationAnnotationView class]];
|
||||
[NSKeyedArchiver archiveRootObject:annotationView toFile:filePath];
|
||||
|
||||
MGLUserLocationAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
|
||||
|
||||
XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled);
|
||||
XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected);
|
||||
XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable);
|
||||
XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset));
|
||||
XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance);
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
@@ -93,6 +93,10 @@
|
||||
357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 357579881D502B06000B822E /* MGLCircleStyleLayerTests.m */; };
|
||||
3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3575798A1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m */; };
|
||||
3575798E1D502EC7000B822E /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3575798D1D502EC7000B822E /* MGLRuntimeStylingHelper.m */; };
|
||||
357FE2DD1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 357FE2DB1E02D2B20068B753 /* NSCoder+MGLAdditions.h */; };
|
||||
357FE2DE1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 357FE2DB1E02D2B20068B753 /* NSCoder+MGLAdditions.h */; };
|
||||
357FE2DF1E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 357FE2DC1E02D2B20068B753 /* NSCoder+MGLAdditions.mm */; };
|
||||
357FE2E01E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 357FE2DC1E02D2B20068B753 /* NSCoder+MGLAdditions.mm */; };
|
||||
3599A3E61DF708BC00E77FB2 /* MGLStyleValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */; };
|
||||
359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */; };
|
||||
35B82BF81D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; };
|
||||
@@ -112,6 +116,7 @@
|
||||
35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
35D13AC51D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */; };
|
||||
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */; };
|
||||
35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */; };
|
||||
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; };
|
||||
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; };
|
||||
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; };
|
||||
@@ -559,6 +564,8 @@
|
||||
3575798C1D502EC7000B822E /* MGLRuntimeStylingHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLRuntimeStylingHelper.h; path = ../../darwin/test/MGLRuntimeStylingHelper.h; sourceTree = "<group>"; };
|
||||
3575798D1D502EC7000B822E /* MGLRuntimeStylingHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLRuntimeStylingHelper.m; path = ../../darwin/test/MGLRuntimeStylingHelper.m; sourceTree = "<group>"; };
|
||||
357F09091DF84F3800941873 /* MGLStyleValueTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleValueTests.h; path = ../../darwin/test/MGLStyleValueTests.h; sourceTree = "<group>"; };
|
||||
357FE2DB1E02D2B20068B753 /* NSCoder+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSCoder+MGLAdditions.h"; path = "../../darwin/src/NSCoder+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
357FE2DC1E02D2B20068B753 /* NSCoder+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "NSCoder+MGLAdditions.mm"; path = "../../darwin/src/NSCoder+MGLAdditions.mm"; sourceTree = "<group>"; };
|
||||
3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleValueTests.m; path = ../../darwin/test/MGLStyleValueTests.m; sourceTree = "<group>"; };
|
||||
359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationAnnotationView_Private.h; sourceTree = "<group>"; };
|
||||
35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
@@ -570,6 +577,7 @@
|
||||
35D13AB61D3D15E300AFB4E0 /* MGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleLayer.mm; sourceTree = "<group>"; };
|
||||
35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFillStyleLayer.h; sourceTree = "<group>"; };
|
||||
35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFillStyleLayer.mm; sourceTree = "<group>"; };
|
||||
35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCodingTests.m; path = ../../darwin/test/MGLCodingTests.m; sourceTree = "<group>"; };
|
||||
35E0CFE51D3E501500188327 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = "<group>"; };
|
||||
35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = "<group>"; };
|
||||
35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNSDataAdditionsTests.m; sourceTree = "<group>"; };
|
||||
@@ -960,6 +968,8 @@
|
||||
35CE61811D4165D9004F2359 /* UIColor+MGLAdditions.mm */,
|
||||
30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */,
|
||||
30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */,
|
||||
357FE2DB1E02D2B20068B753 /* NSCoder+MGLAdditions.h */,
|
||||
357FE2DC1E02D2B20068B753 /* NSCoder+MGLAdditions.mm */,
|
||||
);
|
||||
name = Categories;
|
||||
sourceTree = "<group>";
|
||||
@@ -1095,6 +1105,7 @@
|
||||
DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */,
|
||||
DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */,
|
||||
DA2E885F1CC0382C00F24E7B /* MGLOfflineStorageTests.m */,
|
||||
35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */,
|
||||
DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */,
|
||||
DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */,
|
||||
DA2E88551CC036F400F24E7B /* Info.plist */,
|
||||
@@ -1454,6 +1465,7 @@
|
||||
4018B1C91CDC288A00F666AF /* MGLAnnotationView_Private.h in Headers */,
|
||||
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */,
|
||||
DA88482C1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h in Headers */,
|
||||
357FE2DD1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */,
|
||||
35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */,
|
||||
DA88488E1CBB047F00AB86E3 /* reachability.h in Headers */,
|
||||
@@ -1608,6 +1620,7 @@
|
||||
DA35A2B21CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
|
||||
DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */,
|
||||
DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */,
|
||||
357FE2DE1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
354B83971D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */,
|
||||
DAF0D8111DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */,
|
||||
DABFB86B1CBE99E500D62B32 /* MGLTilePyramidOfflineRegion.h in Headers */,
|
||||
@@ -1976,6 +1989,7 @@
|
||||
DA2E88651CC0382C00F24E7B /* MGLStyleTests.mm in Sources */,
|
||||
DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */,
|
||||
357579801D501E09000B822E /* MGLFillStyleLayerTests.m in Sources */,
|
||||
35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */,
|
||||
DA2E88641CC0382C00F24E7B /* MGLOfflineStorageTests.m in Sources */,
|
||||
DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */,
|
||||
DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
|
||||
@@ -2046,6 +2060,7 @@
|
||||
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
|
||||
35305D481D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
|
||||
DA8848291CBAFA6200AB86E3 /* MGLStyle.mm in Sources */,
|
||||
357FE2DF1E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
|
||||
DA88481C1CBAFA6200AB86E3 /* MGLGeometry.mm in Sources */,
|
||||
3510FFF21D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */,
|
||||
DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */,
|
||||
@@ -2121,6 +2136,7 @@
|
||||
DAA4E4281CBB730400178DFB /* MGLTypes.m in Sources */,
|
||||
DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
|
||||
35305D491D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
|
||||
357FE2E01E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
|
||||
DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */,
|
||||
3510FFF31D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */,
|
||||
DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */,
|
||||
|
||||
@@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
objects and may be recycled later and put into a reuse queue that is maintained
|
||||
by the map view.
|
||||
*/
|
||||
@interface MGLAnnotationImage : NSObject
|
||||
@interface MGLAnnotationImage : NSObject <NSSecureCoding>
|
||||
|
||||
#pragma mark Initializing and Preparing the Image Object
|
||||
|
||||
|
||||
@@ -30,6 +30,44 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super init]) {
|
||||
_image = [decoder decodeObjectOfClass:[UIImage class] forKey:@"image"];
|
||||
_reuseIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"reuseIdentifier"];
|
||||
_enabled = [decoder decodeBoolForKey:@"enabled"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[coder encodeObject:_image forKey:@"image"];
|
||||
[coder encodeObject:_reuseIdentifier forKey:@"reuseIdentifier"];
|
||||
[coder encodeBool:_enabled forKey:@"enabled"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLAnnotationImage class]]) return NO;
|
||||
|
||||
MGLAnnotationImage *otherAnnotationImage = other;
|
||||
|
||||
return ((!_reuseIdentifier && !otherAnnotationImage.reuseIdentifier) || [_reuseIdentifier isEqualToString:otherAnnotationImage.reuseIdentifier])
|
||||
&& _enabled == otherAnnotationImage.enabled
|
||||
&& ((!_image && !otherAnnotationImage.image) || [UIImagePNGRepresentation(_image) isEqualToData:UIImagePNGRepresentation(otherAnnotationImage.image)]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash;
|
||||
hash += [_reuseIdentifier hash];
|
||||
hash += _enabled;
|
||||
hash += [_image hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (void)setImage:(UIImage *)image {
|
||||
_image = image;
|
||||
[self.delegate annotationImageNeedsRedisplay:self];
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
|
||||
interactivity such as dragging, you can use an `MGLAnnotationImage` instead to
|
||||
conserve memory and optimize drawing performance.
|
||||
*/
|
||||
@interface MGLAnnotationView : UIView
|
||||
@interface MGLAnnotationView : UIView <NSSecureCoding>
|
||||
|
||||
#pragma mark Initializing and Preparing the View
|
||||
|
||||
|
||||
@@ -33,6 +33,34 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super initWithCoder:decoder]) {
|
||||
_reuseIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"reuseIdentifier"];
|
||||
_annotation = [decoder decodeObjectOfClass:[NSObject class] forKey:@"annotation"];
|
||||
_centerOffset = [decoder decodeCGVectorForKey:@"centerOffset"];
|
||||
_scalesWithViewingDistance = [decoder decodeBoolForKey:@"scalesWithViewingDistance"];
|
||||
_selected = [decoder decodeBoolForKey:@"selected"];
|
||||
_enabled = [decoder decodeBoolForKey:@"enabled"];
|
||||
self.draggable = [decoder decodeBoolForKey:@"draggable"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeObject:_reuseIdentifier forKey:@"reuseIdentifier"];
|
||||
[coder encodeObject:_annotation forKey:@"annotation"];
|
||||
[coder encodeCGVector:_centerOffset forKey:@"centerOffset"];
|
||||
[coder encodeBool:_scalesWithViewingDistance forKey:@"scalesWithViewingDistance"];
|
||||
[coder encodeBool:_selected forKey:@"selected"];
|
||||
[coder encodeBool:_enabled forKey:@"enabled"];
|
||||
[coder encodeBool:_draggable forKey:@"draggable"];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse
|
||||
{
|
||||
// Intentionally left blank. The default implementation of this method does nothing.
|
||||
|
||||
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
directly. Instead, you retrieve an existing MGLUserLocation object from the
|
||||
`userLocation` property of the map view displayed in your application.
|
||||
*/
|
||||
@interface MGLUserLocation : NSObject <MGLAnnotation>
|
||||
@interface MGLUserLocation : NSObject <MGLAnnotation, NSSecureCoding>
|
||||
|
||||
#pragma mark Determining the User’s Position
|
||||
|
||||
|
||||
@@ -26,6 +26,44 @@ NS_ASSUME_NONNULL_END
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super init]) {
|
||||
_location = [decoder decodeObjectOfClass:[CLLocation class] forKey:@"location"];
|
||||
_title = [decoder decodeObjectOfClass:[NSString class] forKey:@"title"];
|
||||
_subtitle = [decoder decodeObjectOfClass:[NSString class] forKey:@"subtitle"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[coder encodeObject:_location forKey:@"location"];
|
||||
[coder encodeObject:_title forKey:@"title"];
|
||||
[coder encodeObject:_subtitle forKey:@"subtitle"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLUserLocation class]]) return NO;
|
||||
|
||||
MGLUserLocation *otherUserLocation = other;
|
||||
return ((!self.location && !otherUserLocation.location) || [self.location distanceFromLocation:otherUserLocation.location] == 0)
|
||||
&& ((!self.title && !otherUserLocation.title) || [self.title isEqualToString:otherUserLocation.title])
|
||||
&& ((!self.subtitle && !otherUserLocation.subtitle) || [self.subtitle isEqualToString:otherUserLocation.subtitle]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash = [super hash];
|
||||
hash += [_location hash];
|
||||
hash += [_heading hash];
|
||||
hash += [_title hash];
|
||||
hash += [_subtitle hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
|
||||
{
|
||||
return ! [key isEqualToString:@"location"] && ! [key isEqualToString:@"heading"];
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */; };
|
||||
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */; };
|
||||
3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */; };
|
||||
3526EABD1DF9B19800006B43 /* MGLCodingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */; };
|
||||
352742781D4C220900A1ECE6 /* MGLStyleValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742771D4C220900A1ECE6 /* MGLStyleValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
352742811D4C243B00A1ECE6 /* MGLSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3527427F1D4C243B00A1ECE6 /* MGLSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742801D4C243B00A1ECE6 /* MGLSource.mm */; };
|
||||
@@ -34,6 +35,8 @@
|
||||
35602C001D3EA9B40050646F /* MGLForegroundStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 35602BFD1D3EA9B40050646F /* MGLForegroundStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
35602C011D3EA9B40050646F /* MGLForegroundStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.m */; };
|
||||
35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 358EB3AE1D61F0DB00E46D9C /* amsterdam.geojson */; };
|
||||
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 359819571E02F611008FC139 /* NSCoder+MGLAdditions.h */; };
|
||||
3598195A1E02F611008FC139 /* NSCoder+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 359819581E02F611008FC139 /* NSCoder+MGLAdditions.mm */; };
|
||||
3599A3E81DF70E2000E77FB2 /* MGLStyleValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */; };
|
||||
35C5D8471D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35C5D8431D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h */; };
|
||||
35C5D8481D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */; };
|
||||
@@ -252,6 +255,7 @@
|
||||
30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSImage+MGLAdditions.h"; path = "src/NSImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; };
|
||||
3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSExpression+MGLAdditions.mm"; sourceTree = "<group>"; };
|
||||
3526EABC1DF9B19800006B43 /* MGLCodingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCodingTests.m; path = ../../darwin/test/MGLCodingTests.m; sourceTree = "<group>"; };
|
||||
352742771D4C220900A1ECE6 /* MGLStyleValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValue.h; sourceTree = "<group>"; };
|
||||
3527427F1D4C243B00A1ECE6 /* MGLSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource.h; sourceTree = "<group>"; };
|
||||
352742801D4C243B00A1ECE6 /* MGLSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSource.mm; sourceTree = "<group>"; };
|
||||
@@ -276,6 +280,8 @@
|
||||
35602BFD1D3EA9B40050646F /* MGLForegroundStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLForegroundStyleLayer.h; sourceTree = "<group>"; };
|
||||
35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLForegroundStyleLayer.m; sourceTree = "<group>"; };
|
||||
358EB3AE1D61F0DB00E46D9C /* amsterdam.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = amsterdam.geojson; path = ../../darwin/test/amsterdam.geojson; sourceTree = "<group>"; };
|
||||
359819571E02F611008FC139 /* NSCoder+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCoder+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
359819581E02F611008FC139 /* NSCoder+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSCoder+MGLAdditions.mm"; sourceTree = "<group>"; };
|
||||
3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLStyleValueTests.m; sourceTree = "<group>"; };
|
||||
35C5D8431D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSComparisonPredicate+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSComparisonPredicate+MGLAdditions.mm"; sourceTree = "<group>"; };
|
||||
@@ -814,6 +820,8 @@
|
||||
40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */,
|
||||
DAE6C37D1CC31E2A00DB3429 /* NSBundle+MGLAdditions.h */,
|
||||
DAE6C37E1CC31E2A00DB3429 /* NSBundle+MGLAdditions.m */,
|
||||
359819571E02F611008FC139 /* NSCoder+MGLAdditions.h */,
|
||||
359819581E02F611008FC139 /* NSCoder+MGLAdditions.mm */,
|
||||
35C5D8431D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h */,
|
||||
35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */,
|
||||
35C5D8451D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h */,
|
||||
@@ -875,6 +883,7 @@
|
||||
DA8F257D1D51C5F40010E6B5 /* Styling */,
|
||||
DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */,
|
||||
DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */,
|
||||
3526EABC1DF9B19800006B43 /* MGLCodingTests.m */,
|
||||
DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */,
|
||||
DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */,
|
||||
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */,
|
||||
@@ -1015,6 +1024,7 @@
|
||||
DAE6C39A1CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.h in Headers */,
|
||||
DA8F258B1D51CA540010E6B5 /* MGLLineStyleLayer.h in Headers */,
|
||||
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
|
||||
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */,
|
||||
DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */,
|
||||
@@ -1252,6 +1262,7 @@
|
||||
352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */,
|
||||
DAE6C39D1CC31E2A00DB3429 /* NSString+MGLAdditions.m in Sources */,
|
||||
4032C5C61DE1FE9B0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */,
|
||||
3598195A1E02F611008FC139 /* NSCoder+MGLAdditions.mm in Sources */,
|
||||
DAE6C3941CC31E2A00DB3429 /* MGLStyle.mm in Sources */,
|
||||
DAE6C3871CC31E2A00DB3429 /* MGLGeometry.mm in Sources */,
|
||||
3527428E1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm in Sources */,
|
||||
@@ -1321,6 +1332,7 @@
|
||||
DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */,
|
||||
DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */,
|
||||
DA87A9981DC9D88400810D09 /* MGLShapeSourceTests.mm in Sources */,
|
||||
3526EABD1DF9B19800006B43 /* MGLCodingTests.m in Sources */,
|
||||
DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.m in Sources */,
|
||||
3599A3E81DF70E2000E77FB2 /* MGLStyleValueTests.m in Sources */,
|
||||
DAEDC4321D6033F1000224FF /* MGLAttributionInfoTests.m in Sources */,
|
||||
|
||||
@@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
`NSImage` objects with annotation-related metadata. They may be recycled later
|
||||
and put into a reuse queue that is maintained by the map view.
|
||||
*/
|
||||
@interface MGLAnnotationImage : NSObject
|
||||
@interface MGLAnnotationImage : NSObject <NSSecureCoding>
|
||||
|
||||
#pragma mark Initializing and Preparing the Image Object
|
||||
|
||||
|
||||
@@ -23,4 +23,45 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
if (self = [super init]) {
|
||||
_image = [decoder decodeObjectOfClass:[NSImage class] forKey:@"image"];
|
||||
_reuseIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"reuseIdentifier"];
|
||||
_cursor = [decoder decodeObjectOfClass:[NSCursor class] forKey:@"cursor"];
|
||||
_selectable = [decoder decodeBoolForKey:@"selectable"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[coder encodeObject:_image forKey:@"image"];
|
||||
[coder encodeObject:_reuseIdentifier forKey:@"reuseIdentifier"];
|
||||
[coder encodeObject:_cursor forKey:@"cursor"];
|
||||
[coder encodeBool:_selectable forKey:@"selectable"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[MGLAnnotationImage class]]) return NO;
|
||||
|
||||
MGLAnnotationImage *otherAnnotationImage = other;
|
||||
|
||||
return ((!_reuseIdentifier && !otherAnnotationImage.reuseIdentifier) || [_reuseIdentifier isEqualToString:otherAnnotationImage.reuseIdentifier])
|
||||
&& _selectable == otherAnnotationImage.selectable
|
||||
&& ((!_cursor && !otherAnnotationImage.cursor) || [_cursor isEqual:otherAnnotationImage.cursor])
|
||||
&& ((!_image && !otherAnnotationImage.image) || [[_image TIFFRepresentation] isEqualToData:[otherAnnotationImage.image TIFFRepresentation]]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger hash;
|
||||
hash += [_reuseIdentifier hash];
|
||||
hash += _selectable;
|
||||
hash += [_image hash];
|
||||
return hash;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user