diff --git a/Libraries/Geolocation/RCTLocationObserver.m b/Libraries/Geolocation/RCTLocationObserver.m index 5d56caccb..3e864657b 100644 --- a/Libraries/Geolocation/RCTLocationObserver.m +++ b/Libraries/Geolocation/RCTLocationObserver.m @@ -163,12 +163,12 @@ RCT_EXPORT_MODULE() #pragma mark - Public API -RCT_EXPORT_METHOD(startObserving:(NSDictionary *)optionsJSON) +RCT_EXPORT_METHOD(startObserving:(RCTLocationOptions)options) { [self checkLocationConfig]; // Select best options - _observerOptions = [RCTConvert RCTLocationOptions:optionsJSON]; + _observerOptions = options; for (RCTLocationRequest *request in _pendingRequests) { _observerOptions.accuracy = MIN(_observerOptions.accuracy, request.options.accuracy); } @@ -189,7 +189,7 @@ RCT_EXPORT_METHOD(stopObserving) } } -RCT_EXPORT_METHOD(getCurrentPosition:(NSDictionary *)optionsJSON +RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options withSuccessCallback:(RCTResponseSenderBlock)successBlock errorCallback:(RCTResponseSenderBlock)errorBlock) { @@ -219,7 +219,6 @@ RCT_EXPORT_METHOD(getCurrentPosition:(NSDictionary *)optionsJSON } // Check if previous recorded location exists and is good enough - RCTLocationOptions options = [RCTConvert RCTLocationOptions:optionsJSON]; if (_lastLocationEvent && CFAbsoluteTimeGetCurrent() - [RCTConvert NSTimeInterval:_lastLocationEvent[@"timestamp"]] < options.maximumAge && [_lastLocationEvent[@"coords"][@"accuracy"] doubleValue] >= options.accuracy) { diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 67c86fb12..7dc2322f0 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -355,7 +355,7 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName) #define RCT_CONVERT_CASE(_value, _type) \ case _value: { \ - _type (*convert)(id, SEL, id) = (typeof(convert))[RCTConvert methodForSelector:selector]; \ + _type (*convert)(id, SEL, id) = (typeof(convert))objc_msgSend; \ RCT_ARG_BLOCK( _type value = convert([RCTConvert class], selector, json); ) \ break; \ } @@ -377,12 +377,27 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName) RCT_CONVERT_CASE('B', BOOL) RCT_CONVERT_CASE('@', id) RCT_CONVERT_CASE('^', void *) - case '{': - RCTAssert(NO, @"Argument %zd of %C[%@ %@] is defined as %@, however RCT_EXPORT_METHOD() " - "does not currently support struct-type arguments.", i - 2, - [reactMethodName characterAtIndex:0], _moduleClassName, - objCMethodName, argumentName); - break; + + case '{': { + [argumentBlocks addObject:^(RCTBridge *bridge, NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { + NSUInteger size; + NSGetSizeAndAlignment(argumentType, &size, NULL); + void *returnValue = malloc(size); + NSMethodSignature *methodSignature = [RCTConvert methodSignatureForSelector:selector]; + NSInvocation *_invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [_invocation setTarget:[RCTConvert class]]; + [_invocation setSelector:selector]; + [_invocation setArgument:&json atIndex:2]; + [_invocation invoke]; + [_invocation getReturnValue:returnValue]; + + [invocation setArgument:returnValue atIndex:index]; + + free(returnValue); + }]; + break; + } + default: defaultCase(argumentType); } @@ -438,6 +453,10 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName) RCT_SIMPLE_CASE('d', double, doubleValue) RCT_SIMPLE_CASE('B', BOOL, boolValue) + case '{': + RCTLogMustFix(@"Cannot convert JSON to struct %s", argumentType); + break; + default: defaultCase(argumentType); } diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 451a343d0..b7ae182ba 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -1001,12 +1001,11 @@ RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(NSNumber *)reactTag * Only layouts for views that are within the rect passed in are returned. Invokes the error callback if the * passed in parent view does not exist. Invokes the supplied callback with the array of computed layouts. */ -RCT_EXPORT_METHOD(measureViewsInRect:(id)rectJSON +RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect parentView:(NSNumber *)reactTag errorCallback:(RCTResponseSenderBlock)errorCallback callback:(RCTResponseSenderBlock)callback) { - CGRect rect = [RCTConvert CGRect:rectJSON]; RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; if (!shadowView) { RCTLogError(@"Attempting to measure view that does not exist (tag #%@)", reactTag); @@ -1102,9 +1101,8 @@ RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(NSNumber *)reactTag } RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag - withRect:(id)rectJSON) + withRect:(CGRect)rect) { - CGRect rect = [RCTConvert CGRect:rectJSON]; [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ UIView *view = viewRegistry[reactTag]; if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {