Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] MGLMultiPoint now conforms to NSSecureCoding
Browse files Browse the repository at this point in the history
  • Loading branch information
frederoni committed Dec 9, 2016
1 parent c86a01f commit 7ed7782
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 5 deletions.
6 changes: 3 additions & 3 deletions platform/darwin/src/MGLFeature.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ - (instancetype)initWithCoder:(NSCoder *)decoder
self = [super initWithCoder:decoder];
if (self)
{
NSSet<Class> *identifierClasses = [NSSet setWithArray:@[NSString.class, NSNumber.class]];
NSSet<Class> *identifierClasses = [NSSet setWithArray:@[[NSString class], [NSNumber class]]];
identifier = [decoder decodeObjectOfClasses:identifierClasses forKey:@"identifier"];
attributes = [decoder decodeObjectOfClass:NSDictionary.class forKey:@"attributes"];
attributes = [decoder decodeObjectOfClass:[NSDictionary class] forKey:@"attributes"];
}
return self;
}
Expand All @@ -60,7 +60,7 @@ - (BOOL)isEqual:(id)other

- (NSUInteger)hash
{
return [super hash]+[[self geoJSONDictionary] hash];
return [super hash] + [[self geoJSONDictionary] hash];
}

- (id)attributeForKey:(NSString *)key {
Expand Down
86 changes: 86 additions & 0 deletions platform/darwin/src/MGLMultiPoint.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,37 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/optional.hpp>

bool compareByCoordinate(CLLocationCoordinate2D lhs, CLLocationCoordinate2D rhs)
{
return lhs.latitude+lhs.longitude < rhs.latitude+rhs.longitude;
}

bool operator!=(const CLLocationCoordinate2D lhs, const CLLocationCoordinate2D rhs) {
return lhs.latitude != rhs.latitude || lhs.longitude != rhs.longitude;
}

bool operator==(std::vector<CLLocationCoordinate2D>& lhs, std::vector<CLLocationCoordinate2D>& rhs)
{
if (lhs.size() != rhs.size()) return false;

std::sort(lhs.begin(), lhs.end(), compareByCoordinate);
std::sort(rhs.begin(), rhs.end(), compareByCoordinate);

auto itLhs = lhs.begin();
auto itRhs = rhs.begin();

while (itLhs != lhs.end() || itRhs != rhs.end())
{
if (*itLhs != *itRhs)
return false;

if (itLhs != lhs.end()) ++itLhs;
if (itRhs != rhs.end()) ++itRhs;
}

return true;
}

@implementation MGLMultiPoint
{
mbgl::optional<mbgl::LatLngBounds> _bounds;
Expand All @@ -27,6 +58,61 @@ - (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count
return self;
}

- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self)
{
NSArray *coordinates = [decoder decodeObjectOfClass:[NSArray class] forKey:@"coordinates"];
CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc([coordinates count] * sizeof(CLLocationCoordinate2D));
for (NSUInteger i = 0; i < [coordinates count]; i++)
{
coords[i] = CLLocationCoordinate2DMake([coordinates[i][0] doubleValue], [coordinates[i][1] doubleValue]);
}
_coordinates = { coords, coords + [coordinates count] };
free(coords);
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];

NSMutableArray *coordinates = [NSMutableArray array];
for (auto coord : _coordinates) {
[coordinates addObject:@[@(coord.latitude), @(coord.longitude)]];
}
[coder encodeObject:coordinates forKey:@"coordinates"];
}

- (BOOL)isEqual:(id)other
{
if (self == other) return YES;

MGLMultiPoint *otherMultipoint = other;

CLLocationCoordinate2D *otherCoordinates = [otherMultipoint coordinates];
std::vector<CLLocationCoordinate2D> otherCoords;
otherCoords.reserve([otherMultipoint pointCount]);

for (NSUInteger i = 0; i < [otherMultipoint pointCount]; i++) {
otherCoords.push_back(otherCoordinates[i]);
}

return ([super isEqual:otherMultipoint]
&& _coordinates == otherCoords);
}

- (NSUInteger)hash
{
NSUInteger hash = [super hash];
for (auto coord : _coordinates) {
hash += coord.latitude+coord.longitude;
}
return hash;
}

- (CLLocationCoordinate2D)coordinate
{
NSAssert([self pointCount] > 0, @"A multipoint must have coordinates");
Expand Down
3 changes: 1 addition & 2 deletions platform/darwin/src/MGLPointAnnotation.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ - (BOOL)isEqual:(id)other

- (NSUInteger)hash
{
return @(self.coordinate.latitude).hash+@(self.coordinate.longitude).hash
+self.title.hash+self.subtitle.hash;
return [super hash] + @(self.coordinate.latitude).hash + @(self.coordinate.longitude).hash;
}

- (NSString *)description
Expand Down
27 changes: 27 additions & 0 deletions platform/darwin/test/MGLCodingTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,31 @@ - (void)testPointFeature {
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);
}

@end

0 comments on commit 7ed7782

Please sign in to comment.