Skip to content

Commit

Permalink
* [ios] feature: separate callNativeModule and callNativeComponent fr…
Browse files Browse the repository at this point in the history
…om callName and support calling module method synchronously.
  • Loading branch information
cxfeng1 committed Dec 21, 2016
1 parent 03ab948 commit aa50df0
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 58 deletions.
4 changes: 4 additions & 0 deletions ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m
Expand Up @@ -13,6 +13,10 @@ @implementation JSValue (Weex)

+ (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context
{
if (!invocation || !context) {
return nil;
}

char returnType[255];
strcpy(returnType, [invocation.methodSignature methodReturnType]);

Expand Down
14 changes: 8 additions & 6 deletions ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
Expand Up @@ -116,7 +116,7 @@ - (void)registerGlobalFuntions
return 0;
}];

[_jsBridge registerCallNativeModule:^id(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options) {
[_jsBridge registerCallNativeModule:^NSInvocation*(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *arguments, NSDictionary *options) {

WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];

Expand All @@ -125,11 +125,14 @@ - (void)registerGlobalFuntions
return nil;
}

return nil;
WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:arguments instance:instance];
return [method invoke];
}];

[_jsBridge registerCallNativeComponent:^id(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) {
return nil;
[_jsBridge registerCallNativeComponent:^void(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) {
WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:componentRef methodName:methodName arguments:args instance:instance];
[method invoke];
}];
}

Expand Down Expand Up @@ -184,9 +187,8 @@ - (NSInteger)invokeNative:(NSString *)instanceId tasks:(NSArray *)tasks callback
NSString *methodName = task[@"method"];
NSArray *arguments = task[@"args"];
if (task[@"component"]) {
NSString *componentName = task[@"component"];
NSString *ref = task[@"ref"];
WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentName:componentName componentRef:ref methodName:methodName arguments:arguments instance:instance];
WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:ref methodName:methodName arguments:arguments instance:instance];
[method invoke];
} else {
NSString *moduleName = task[@"module"];
Expand Down
9 changes: 4 additions & 5 deletions ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h
Expand Up @@ -11,11 +11,10 @@

@interface WXComponentMethod : WXBridgeMethod

- (instancetype)initWithComponentName:(NSString *)componentName
componentRef:(NSString *)ref
methodName:(NSString *)methodName
arguments:(NSArray *)arguments
instance:(WXSDKInstance *)instance;
- (instancetype)initWithComponentRef:(NSString *)ref
methodName:(NSString *)methodName
arguments:(NSArray *)arguments
instance:(WXSDKInstance *)instance;

- (void)invoke;

Expand Down
12 changes: 5 additions & 7 deletions ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m
Expand Up @@ -19,14 +19,12 @@ @implementation WXComponentMethod
NSString *_componentRef;
}

- (instancetype)initWithComponentName:(NSString *)componentName
componentRef:(NSString *)ref
methodName:(NSString *)methodName
arguments:(NSArray *)arguments
instance:(WXSDKInstance *)instance
- (instancetype)initWithComponentRef:(NSString *)ref
methodName:(NSString *)methodName
arguments:(NSArray *)arguments
instance:(WXSDKInstance *)instance
{
if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) {
_componentName = componentName;
_componentRef = ref;
}

Expand All @@ -40,7 +38,7 @@ - (void)invoke
if (!component) {
WXLogError(@"component not found for ref:%@, type:%@", _componentRef, _componentName);
}
SEL selector = [WXComponentFactory methodWithComponentName:_componentName withMethod:self.methodName];
SEL selector = [WXComponentFactory methodWithComponentName:component.type withMethod:self.methodName];
NSInvocation * invocation = [self invocationWithTarget:component selector:selector];
WXPerformBlockOnMainThread(^{
[invocation invoke];
Expand Down
18 changes: 15 additions & 3 deletions ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
Expand Up @@ -20,6 +20,7 @@
#import <sys/utsname.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import "WXPolyfillSet.h"
#import "JSValue+Weex.h"

#import <dlfcn.h>

Expand Down Expand Up @@ -167,13 +168,24 @@ - (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock

WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, moduleNameString, methodNameString, argsArray);

return callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic);
NSInvocation *invocation = callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic);
return [JSValue wx_valueWithReturnValueFromInvocation:invocation inContext:[JSContext currentContext]];
};
}

- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock
- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock
{

_jsContext[@"callNativeComponent"] = ^void(JSValue *instanceId, JSValue *componentName, JSValue *methodName, JSValue *args, JSValue *options) {
NSString *instanceIdString = [instanceId toString];
NSString *componentNameString = [componentName toString];
NSString *methodNameString = [methodName toString];
NSArray *argsArray = [args toArray];
NSDictionary *optionsDic = [options toDictionary];

WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, componentNameString, methodNameString, argsArray);

callNativeComponentBlock(instanceIdString, componentNameString, methodNameString, argsArray, optionsDic);
};
}

- (JSValue*)exception
Expand Down
13 changes: 9 additions & 4 deletions ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
Expand Up @@ -38,7 +38,8 @@ - (NSInvocation *)invoke

id<WXModuleProtocol> moduleInstance = [self.instance moduleForClass:moduleClass];
WXAssert(moduleInstance, @"No instance found for module name:%@, class:%@", _moduleName, moduleClass);
SEL selector = [WXModuleFactory methodWithModuleName:self.moduleName withMethod:self.methodName];
BOOL isSync;
SEL selector = [WXModuleFactory selectorWithModuleName:self.moduleName methodName:self.methodName isSync:&isSync];
if (!selector) {
NSString *errorMessage = [NSString stringWithFormat:@"method:%@ for module:%@ doesn't exist, maybe it has not been registered", self.methodName, _moduleName];
WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage);
Expand All @@ -47,9 +48,13 @@ - (NSInvocation *)invoke

NSInvocation *invocation = [self invocationWithTarget:moduleInstance selector:selector];

[self _dispatchInvovation:invocation moduleInstance:moduleInstance];

return nil;
if (isSync) {
[invocation invoke];
return invocation;
} else {
[self _dispatchInvovation:invocation moduleInstance:moduleInstance];
return nil;
}
}

- (void)_dispatchInvovation:(NSInvocation *)invocation moduleInstance:(id<WXModuleProtocol>)moduleInstance
Expand Down
6 changes: 3 additions & 3 deletions ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
Expand Up @@ -117,7 +117,7 @@ - (NSMutableDictionary *)_componentMethodMapsWithName:(NSString *)name
void (^mBlock)(id, id, BOOL *) = ^(id mKey, id mObj, BOOL * mStop) {
[methods addObject:mKey];
};
[config.methods enumerateKeysAndObjectsUsingBlock:mBlock];
[config.asyncMethods enumerateKeysAndObjectsUsingBlock:mBlock];
[_configLock unlock];

return dict;
Expand All @@ -132,8 +132,8 @@ - (SEL)_methodWithComponnetName:(NSString *)name withMethod:(NSString *)method

[_configLock lock];
config = [_componentConfigs objectForKey:name];
if (config.methods) {
selStr = [config.methods objectForKey:method];
if (config.asyncMethods) {
selStr = [config.asyncMethods objectForKey:method];
}
if (selStr) {
selector = NSSelectorFromString(selStr);
Expand Down
3 changes: 2 additions & 1 deletion ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h
Expand Up @@ -17,7 +17,8 @@
/**
* The methods map
**/
@property (nonatomic, strong) NSMutableDictionary *methods;
@property (nonatomic, strong) NSMutableDictionary *asyncMethods;
@property (nonatomic, strong) NSMutableDictionary *syncMethods;

+ (instancetype)sharedInstance;
- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz;
Expand Down
19 changes: 13 additions & 6 deletions ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m
Expand Up @@ -39,16 +39,16 @@ - (instancetype)init
{

if (self = [super init]) {
_methods = [NSMutableDictionary new];
_asyncMethods = [NSMutableDictionary new];
_syncMethods = [NSMutableDictionary new];
}

return self;
}

- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz
{
if (self = [super init]) {
_methods = [NSMutableDictionary new];
if (self = [self init]) {
_name = name;
_clazz = clazz;
}
Expand All @@ -69,8 +69,14 @@ - (void)registerMethods
Method *methodList = class_copyMethodList(object_getClass(currentClass), &methodCount);
for (unsigned int i = 0; i < methodCount; i++) {
NSString *selStr = [NSString stringWithCString:sel_getName(method_getName(methodList[i])) encoding:NSUTF8StringEncoding];

if (![selStr hasPrefix:@"wx_export_method_"]) continue;
BOOL isSyncMethod;
if ([selStr hasPrefix:@"wx_export_method_sync_"]) {
isSyncMethod = YES;
} else if ([selStr hasPrefix:@"wx_export_method_"]) {
isSyncMethod = NO;
} else {
continue;
}

NSString *name = nil, *method = nil;
SEL selector = NSSelectorFromString(selStr);
Expand All @@ -90,7 +96,8 @@ - (void)registerMethods
name = method;
}

[_methods setObject:method forKey:name];
NSMutableDictionary *methods = isSyncMethod ? _syncMethods : _asyncMethods;
[methods setObject:method forKey:name];
}

free(methodList);
Expand Down
4 changes: 2 additions & 2 deletions ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h
Expand Up @@ -26,12 +26,12 @@
* @param method The module method
*
**/
+ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method;
+ (SEL)selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync;

/**
* @abstract Registers a module for a given name and the implemented class
*
* @param module The module name to register
* @param name The module name to register
*
* @param clazz The module class to register
*
Expand Down
24 changes: 14 additions & 10 deletions ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m
Expand Up @@ -83,24 +83,27 @@ - (Class)_classWithModuleName:(NSString *)name
return NSClassFromString(config.clazz);
}

- (SEL)_methodWithModuleName:(NSString *)name withMethod:(NSString *)method
- (SEL)_selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync
{
WXAssert(name && method, @"Fail to find selector with module name and method, please check if the parameters are correct !");

NSString *selStr = nil; SEL selector = nil;
NSString *selectorString = nil;;
WXModuleConfig *config = nil;

[_moduleLock lock];
config = [_moduleMap objectForKey:name];
if (config.methods) {
selStr = [config.methods objectForKey:method];
if (config.syncMethods) {
selectorString = [config.syncMethods objectForKey:method];
if (selectorString && isSync) {
*isSync = YES;
}
}
if (selStr) {
selector = NSSelectorFromString(selStr);
if (!selectorString && config.asyncMethods) {
selectorString = [config.asyncMethods objectForKey:method];;
}
[_moduleLock unlock];

return selector;
return NSSelectorFromString(selectorString);
}

- (NSString *)_registerModule:(NSString *)name withClass:(Class)clazz
Expand Down Expand Up @@ -131,7 +134,8 @@ - (NSMutableDictionary *)_moduleMethodMapsWithName:(NSString *)name
void (^mBlock)(id, id, BOOL *) = ^(id mKey, id mObj, BOOL * mStop) {
[methods addObject:mKey];
};
[config.methods enumerateKeysAndObjectsUsingBlock:mBlock];
[config.syncMethods enumerateKeysAndObjectsUsingBlock:mBlock];
[config.asyncMethods enumerateKeysAndObjectsUsingBlock:mBlock];
[_moduleLock unlock];

return dict;
Expand Down Expand Up @@ -160,9 +164,9 @@ + (Class)classWithModuleName:(NSString *)name
return [[self _sharedInstance] _classWithModuleName:name];
}

+ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method
+ (SEL)selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync
{
return [[self _sharedInstance] _methodWithModuleName:name withMethod:method];
return [[self _sharedInstance] _selectorWithModuleName:name methodName:method isSync:isSync];
}

+ (NSString *)registerModule:(NSString *)name withClass:(Class)clazz
Expand Down
10 changes: 5 additions & 5 deletions ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
Expand Up @@ -8,10 +8,10 @@

#import <JavaScriptCore/JavaScriptCore.h>

typedef NSInteger (^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback);
typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index);
typedef id (^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options);
typedef id (^WXJSCallNativeComponent)(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options);
typedef NSInteger(^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback);
typedef NSInteger(^WXJSCallAddElement)(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index);
typedef NSInvocation *(^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options);
typedef void (^WXJSCallNativeComponent)(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options);

@protocol WXBridgeProtocol <NSObject>

Expand Down Expand Up @@ -58,7 +58,7 @@ typedef id (^WXJSCallNativeComponent)(NSString *instancdId, NSString *componentR
/**
* Register callback for global js function `callNativeComponent`
*/
- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock;
- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock;


@end
17 changes: 12 additions & 5 deletions ios/sdk/WeexSDK/Sources/Utility/WXDefine.h
Expand Up @@ -70,16 +70,23 @@ parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];\

#define WX_FONT_DOWNLOAD_DIR [[WXUtility cacheDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:@"wxdownload"]]

#define WX_EXPORT_METHOD_INTERNAL(method, token) \
+ (NSString *)WX_CONCAT_WRAPPER(token, __LINE__) { \
return NSStringFromSelector(method); \
}

/**
* @abstract export public method
*/
#define WX_EXPORT_METHOD(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_)

#define WX_EXPORT_METHOD(method) \
+ (NSString *)WX_CONCAT_WRAPPER(wx_export_method_, __LINE__) { \
return NSStringFromSelector(method); \
}
/**
* @abstract export public method, support sync return value
* @warning the method can only be called on js thread
*/
#define WX_EXPORT_METHOD_SYNC(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_sync_)

/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name)
/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name)
* so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function.
* http://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c
*/
Expand Down
2 changes: 1 addition & 1 deletion ios/sdk/WeexSDKTests/WXSDKEngineTests.m
Expand Up @@ -57,7 +57,7 @@ - (void)testRegisterModule {
Class cls = [WXModuleFactory classWithModuleName:@"stream"];
XCTAssertEqualObjects(NSStringFromClass(cls), @"WXStreamModule");

SEL selector = [WXModuleFactory methodWithModuleName:@"stream" withMethod:@"fetch"];
SEL selector = [WXModuleFactory selectorWithModuleName:@"stream" methodName:@"fetch" isSync:nil];
XCTAssertEqualObjects(NSStringFromSelector(selector), @"fetch:callback:progressCallback:");
}

Expand Down

0 comments on commit aa50df0

Please sign in to comment.