diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2018-03-16 10:17:32 -0700 |
---|---|---|
committer | Fabian Guerra <fabian.guerra@mapbox.com> | 2018-03-28 19:31:53 -0400 |
commit | 09810d53bf224e68ba4cbe95cf633f4ad6c29592 (patch) | |
tree | 65a49b209125084d5db41be263179e5d739eb0d7 | |
parent | 2aaa038ef182cbba3095fa7636c15ab376f87b84 (diff) | |
download | qtlocation-mapboxgl-09810d53bf224e68ba4cbe95cf633f4ad6c29592.tar.gz |
[ios, macos] Introduced more ergonomic expression concatenation syntax
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 43 | ||||
-rw-r--r-- | platform/darwin/test/MGLExpressionTests.mm | 5 |
2 files changed, 44 insertions, 4 deletions
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index a193b85caa..cb9f5813f3 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -11,8 +11,47 @@ #import "NSPredicate+MGLAdditions.h" #import "NSValue+MGLStyleAttributeAdditions.h" +#import <objc/runtime.h> + #import <mbgl/style/expression/expression.hpp> +/** + Joins the given components into a single string by concatenating each component + in order. + */ +NSString *MGLJoinComponents(Class self, SEL _cmd, NSArray<NSString *> *components) { + return [components componentsJoinedByString:@""]; +} + +/** + Adds to NSExpression’s built-in repertoire of functions. + */ +void MGLEndowExpressionsWithCustomFunctions() { + // NSExpression’s built-in functions are backed by class methods on a + // private class, so use a function expression to get at the class. + // http://funwithobjc.tumblr.com/post/2922267976/using-custom-functions-with-nsexpression + NSExpression *functionExpression = [NSExpression expressionWithFormat:@"sum({})"]; + NSString *className = NSStringFromClass([functionExpression.operand.constantValue class]); + + // Effectively categorize the class with some extra class methods. + Class NSPredicateUtilities = objc_getMetaClass(className.UTF8String); +#pragma clang push +#pragma clang diagnostic ignored "-Wundeclared-selector" + class_addMethod(NSPredicateUtilities, @selector(mgl_join:), (IMP)MGLJoinComponents, "@@:@"); +#pragma clang pop +} + +@interface MGLExpressionEndowmentLoader: NSObject +@end + +@implementation MGLExpressionEndowmentLoader + ++ (void)load { + MGLEndowExpressionsWithCustomFunctions(); +} + +@end + @implementation NSExpression (MGLPrivateAdditions) - (std::vector<mbgl::Value>)mgl_aggregateMBGLValue { @@ -415,9 +454,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { return [NSExpression expressionForConstantValue:@(M_PI)]; } else if ([op isEqualToString:@"concat"]) { NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects); - NSExpression *operand = subexpressions.firstObject; - subexpressions = [subexpressions subarrayWithRange:NSMakeRange(1, subexpressions.count - 1)]; - return [NSExpression expressionForFunction:operand selectorName:@"stringByAppendingString:" arguments:subexpressions]; + return [NSExpression expressionForFunction:@"mgl_join" arguments:subexpressions]; } else if ([op isEqualToString:@"at"]) { NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects); NSExpression *index = subexpressions.firstObject; diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index d189b41cd7..a78126ef95 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -510,10 +510,13 @@ using namespace std::string_literals; NSArray *arguments = @[MGLConstantExpression(@"MacDonald")]; { NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')"]; + NSExpression *customExpression = [NSExpression expressionWithFormat:@"mgl_join({'Old', 'McDonald'})"]; NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects(customExpression.mgl_jsonExpressionObject, jsonExpression); XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald"); - XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); + XCTAssertEqualObjects([customExpression expressionValueWithObject:nil context:nil], @"OldMacDonald"); + XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], customExpression); } { NSExpression *expression = [NSExpression expressionForFunction:@"uppercase:" arguments:arguments]; |