cocos2dx js调用Ojbect c, 回调函数修改jsb.reflection.callStaticMethod

    xiaoxiao2021-12-14  17

    js可以直接调用object c方法, 必须是静态方法。其中的过程,在JavaScriptObjectBridge中写的很详细。

    此次使用的cocos2dx的版本为3.13。 这个方法有个问题, 传给Object c的参数, 只能为基本数据类型,不能是js对象。 其中也包括function 对象。在使用过程中, 不是特别方便。

    基本思路就是, 把js传入的对象保存, 封装成Object c对象, 方便使用完成后,进行调用。

    处理js传入参数的方法接口为:

    bool JavaScriptObjCBridge::CallInfo::execute(JSContext *cx,jsval *argv,unsigned argc) { //...... if(arg.isObject() || arg.isObject()){ m_dic = NULL; m_error = JSO_ERR_TYPE_NOT_SUPPORT; return false; } //....... } 省略无相关代码, 可以看到, 如果为js对象, 则直接放回false, 调用失败。

    这里, 我们自定义一个类:JSBridgeForCallBack, 

    //struct JSContext; @interface JSBridgeForCallBack : NSObject //set js object - (void)setJsval:(void *) val; - (void *)getJsval; //set param //set json - (void)setParamDict:(NSDictionary *)param atIndex:(NSInteger)index; //set string - (void)setParamString:(NSString *)param atIndex:(NSInteger)index; //long - (void)setPramlong:(long)param atIndex:(NSInteger)index; //double - (void)setParamDouble:(double)param atIndex:(NSInteger)index; //run call back function - (void)run; // - (void)setJSContext:(struct JSContext *)cx; @end 修改JavaScriptObjCBridge::CallInfo::execute。 (NSinvocation 这个在这里就不做介绍了。)

    bool JavaScriptObjCBridge::CallInfo::execute(JSContext *cx,jsval *argv,unsigned argc) { //... if(arg.isObject() || arg.isObject()){ //此处保存传过来的对象 JSBridgeForCallBack *callobj = [[JSBridgeForCallBack alloc] init]; [callobj setJSContext:cx]; [callobj setJsval:(void*)&arg]; [m_dic setObject:callobj forKey:key]; // m_dic = NULL; // m_error = JSO_ERR_TYPE_NOT_SUPPORT; // return false; //... //... if(m_dic != nil){ for(int i = 2;i<m_dic.count+2;i++){ id obj = [m_dic objectForKey:[NSString stringWithFormat:@"argument%d",i-2] ]; if ([obj isKindOfClass:[NSNumber class]] && ((strcmp([obj objCType], "c") == 0 || strcmp([obj objCType], "B") == 0))) //BOOL { bool b = [obj boolValue]; [invocation setArgument:&b atIndex:i]; } //判断上面保存的参数, 是否为JSBridgeForCallBack, else if([obj isKindOfClass:[JSBridgeForCallBack class]]) // call back function { [invocation setArgument:&obj atIndex:i]; } else { [invocation setArgument:&obj atIndex:i]; } } } /.. } 现在来测试一下, 修改的结果。 定义一个测试类, 

    #import <Foundation/Foundation.h> @class JSBridgeForCallBack; @interface libGameCenter : NSObject + (BOOL)printStr:(NSString *)send by:(JSBridgeForCallBack *) callback; @end #import "libGameCenter.h" #import "JSBridgeForCallBack.h" @implementation libGameCenter + (BOOL)printStr:(NSString *)send by:(JSBridgeForCallBack *) callback { NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"123", @"def", nil]; [callback setParamDict:dict atIndex:1]; [callback setParamDouble:send atIndex:0]; [callback run]; return YES; } @end

    我们在main.js中调用改方法, 注意需要将该类加载一次,  objectc , 如果不加载一次, NSClassFromString 无法找到方法。具体操作在AppController.mm中,

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //.... [libGameCenter load]; //.... } 在main.js中, 定义一个function

    var callbackfunction = function(send, json) { cc.log("callbackfunction !!!!!!!!!!!!!" + send); cc.log("json 2 = " + json["def"]); } cc.game.onStart = function(){ var cb = callbackfunction; var ret = jsb.reflection.callStaticMethod("libGameCenter", "printStr:by:", "send to object c", cb); //... }; cc.game.run();

    测试结果如图, 已经调用成功。

     总结:

    1.存在问题:如果回调js, 传的参数如果为dictionary, 在解析过后, 无法JSON.stringify(json), 进行打印, 没有找到原因,  猜测传入不是json对象。 解决办法是传入json字符串, 在js中, 把字符串转为json对象。

    2.没有进行异常处理, 如果有朋友要使用, 有上面问题欢迎交流。

    3.引用JSBridgeForCallBack头文件的时候, 只能在.m中调用, 在.h 中进行一次申明 @class JSBridgeForCallback 。否则会提示头文件在不到。

    4.代码传送门,替换cocos/scripting/js-bindings/manual/platform/ios下的文件即可。

    转载请注明原文地址: https://ju.6miu.com/read-969348.html

    最新回复(0)