| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #import "WXBridgeMethod.h" |
| #import "WXSDKInstance.h" |
| #import "WXMonitor.h" |
| #import "WXAssert.h" |
| #import "WXUtility.h" |
| #import "WXSDKManager.h" |
| #import <objc/runtime.h> |
| #import "WXConvert.h" |
| |
| @implementation WXBridgeMethod |
| |
| - (instancetype)initWithMethodName:(NSString *)methodName arguments:(NSArray *)arguments instance:(WXSDKInstance *)instance |
| { |
| if (self = [super init]) { |
| _methodName = methodName; |
| _arguments = [NSMutableArray arrayWithArray:arguments]; |
| _instance = instance; |
| } |
| |
| return self; |
| } |
| |
| - (NSString *)description |
| { |
| return [NSString stringWithFormat:@"<%@: %p; instance = %@; method = %@; arguments= %@>", NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments]; |
| } |
| |
| //check parameter:NSNumber contains int,float,double;object contains nsarray,nsstring,nsdictionary ;block is block |
| //https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html |
| -(id)parseArgument:(id)obj parameterType:(const char *)parameterType order:(int)order |
| { |
| #ifdef DEBUG |
| BOOL check = YES; |
| #endif |
| if (strcmp(parameterType,@encode(float))==0 || strcmp(parameterType,@encode(double))==0) |
| { |
| #ifdef DEBUG |
| check = [obj isKindOfClass:[NSNumber class]]; |
| if(!check){ |
| NSLog(@"<%@: %p; instance = %@; method = %@; arguments= %@; the number %d parameter type is not right,it should be float or double>",NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments,order); |
| } |
| #endif |
| CGFloat value = [WXConvert CGFloat:obj]; |
| return [NSNumber numberWithDouble:value]; |
| } else if (strcmp(parameterType,@encode(int))==0) { |
| #ifdef DEBUG |
| check = [obj isKindOfClass:[NSNumber class]]; |
| if(!check){ |
| NSLog(@"<%@: %p; instance = %@; method = %@; arguments= %@; the number %d parameter type is not right,it should be int>",NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments,order); |
| } |
| #endif |
| NSInteger value = [WXConvert NSInteger:obj]; |
| return [NSNumber numberWithInteger:value]; |
| } else if(strcmp(parameterType,@encode(id))==0) { |
| #ifdef DEBUG |
| check = [obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDictionary class]] ||[obj isKindOfClass:[NSString class]]; |
| if(!check){ |
| NSLog(@"<%@: %p; instance = %@; method = %@; arguments= %@ ;the number %d parameter type is not right,it should be array ,map or string>",NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments,order); |
| } |
| #endif |
| return obj; |
| } else if(strcmp(parameterType,@encode(typeof(^{})))==0) { |
| #ifdef DEBUG |
| check = [obj isKindOfClass:[NSString class]]; // jsfm pass string if parameter type is block |
| if(!check){ |
| NSLog(@"<%@: %p; instance = %@; method = %@; arguments= %@; the number %d parameter type is not right,it should be block>",NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments,order); |
| } |
| #endif |
| return obj; |
| } |
| return obj; |
| } |
| |
| - (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector |
| { |
| WXAssert(target, @"No target for method:%@", self); |
| WXAssert(selector, @"No selector for method:%@", self); |
| |
| NSMethodSignature *signature = [target methodSignatureForSelector:selector]; |
| if (!signature) { |
| NSString *errorMessage = [NSString stringWithFormat:@"target:%@, selector:%@ doesn't have a method signature", target, NSStringFromSelector(selector)]; |
| WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); |
| return nil; |
| } |
| |
| NSUInteger redundantArgumentCount = 0; |
| NSArray *arguments = _arguments; |
| if (signature.numberOfArguments - 2 < arguments.count) { |
| redundantArgumentCount = arguments.count - (signature.numberOfArguments - 2); // JS provides more arguments than required. |
| } |
| |
| NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; |
| invocation.target = target; |
| invocation.selector = selector; |
| NSString *instanceId = _instance.instanceId; |
| void **freeList = NULL; |
| |
| NSMutableArray *blockArray = [NSMutableArray array]; |
| WX_ALLOC_FLIST(freeList, arguments.count - redundantArgumentCount); |
| for (int i = 0; i < arguments.count - redundantArgumentCount; i ++ ) { |
| id obj = arguments[i]; |
| const char *parameterType = [signature getArgumentTypeAtIndex:i + 2]; |
| obj = [self parseArgument:obj parameterType:parameterType order:i]; |
| static const char *blockType = @encode(typeof(^{})); |
| id argument; |
| if (!strcmp(parameterType, blockType)) { |
| // callback |
| argument = [^void(NSString *result, BOOL keepAlive) { |
| [[WXSDKManager bridgeMgr] callBack:instanceId funcId:(NSString *)obj params:result keepAlive:keepAlive]; |
| } copy]; |
| |
| // retain block |
| [blockArray addObject:argument]; |
| [invocation setArgument:&argument atIndex:i + 2]; |
| } else { |
| argument = obj; |
| WX_ARGUMENTS_SET(invocation, signature, i, argument, freeList); |
| } |
| } |
| [invocation retainArguments]; |
| WX_FREE_FLIST(freeList, arguments.count - redundantArgumentCount); |
| |
| return invocation; |
| } |
| |
| @end |