CocosCreator与Object-C的交互--Object-C原生反射机制

说明

Cocos Creator 项目发布到IOS中用到。

环境:MAC电脑, xCode11,CocosCreator2.3.1。

首先,cocos creator 文档介绍:https://docs.cocos.com/creator/manual/zh/advanced-topics/oc-reflection.html

看完文档后,进入实际操作步骤:

这里先看 object-c 如何调用 js/ts

1.新建类CallJS的头文件:CallJS.h

xcode 中新建 .h 文件 (文件名随意)。这里命名:CallJS.h

定义与 js/ts 交互的函数名字。

代码如下:

#import <UIKit/UIKit.h>

@interface CallJS : NSObject
{
}

/*
 object-c 调用 cocos creator 固定节点绑定的固定(js/ts)脚本的固定函数,并且该函数有个1个参数。
 固定(js/ts)脚本:(object-c中写死的脚本名字,cocose creator 中必须要有此脚本,并且挂在了 object-c 中写死的节点名字上)。
 固定函数:(object-c中写死的函数名。此函数必须在固定脚本中存在,并且名字相同,参数个数与类型都必须相同)。
 **/
+(void)callJsCCNodeFunc_1:(NSString*) cmdStr;
/**
 object-c 调用 cocos creator 固定节点绑定的固定(js/ts)脚本的 funcNameStr函数(funcNameStr:代表函数名字符串),并且该函数有个2个参数。
 固定(js/ts)脚本:(object-c中写死的脚本名字,cocose creator 中必须要有此脚本,并且挂在了 object-c 中写死的节点名字上)。
 固定函数:(object-c中写死的函数名。此函数必须在固定脚本中存在,并且名字相同,参数个数与类型都必须相同)。
 */
+(void)callJsCCNodeFunc_3:(NSString*) funcNameStr withCmd:(NSString*) cmdStr withContent:(NSString*) contentStr;

/**
 object-c 调用 cocos creator 中(js/ts)脚本中的全局的funcNameStr函数(funcNameStr:代表函数名字符串),并且该函数有个0个参数。
 */
+(void)callJsGlobalFunc_1:(NSString*) funcNameStr;
/**
 object-c 调用 cocos creator 中(js/ts)脚本中的全局的funcNameStr函数(funcNameStr:代表函数名字符串),并且该函数有个1个参数。
 */
+(void)callJsGlobalFunc_2:(NSString*) funcNameStr withCmd:(NSString*) cmdStr;
/**
 object-c 调用 cocos creator 中(js/ts)脚本中的全局的funcNameStr函数(funcNameStr:代表函数名字符串),并且该函数有个2个参数。
 */
+(void)callJsGlobalFunc_3:(NSString*) funcNameStr withCmd:(NSString*) cmdStr withContent:(NSString*) contentStr;

@end

2.实现类CallJS的文件:CallJS.mm

新建文件 CallJS.m (注意-->>新建文件后,在xcode中将文件名改名为 CallJS.mm 至于为什么要将 .m 文件改名为 .mm 文件,可以去百度下这两种文件的区别,我是个小白,无法解释太多。)实现 CallJS.h 中到函数。

实现与js/ts交换的函数。

代码如下:


#import <Foundation/Foundation.h>

#import "cocos2d.h"
#import "CallJS.h"

// 这个.h文件必须导入,否则报错。
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
//using namespace std;

@implementation CallJS

+(void)callJsCCNodeFunc_1:(NSString*) cmdStr{
    
    NSLog(@"-------callJsCCNodeFunc_1...");
    
    std::string param001 = [cmdStr UTF8String];
    
    // "cc.find('AppMain').getComponent('IOSCtrl').GetAward(\"%s\");", param001.c_str()
    // 可以理解为:调用 cc.find() 函数在场景中查找 AppMain 节点,在利用 getComponent() 函数获取该节点下 名为 IOSCtrl.ts 的脚本。最后调用 脚本中的成员函数 GetAward(),此函数有一个参数。
    std::string jsCallStr = cocos2d::StringUtils::format("cc.find('AppMain').getComponent('IOSCtrl').GetAward(\"%s\");", param001.c_str());
    NSLog(@"--------- jsCallStr = %s", jsCallStr.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}

+(void)callJsCCNodeFunc_3:(NSString*) funcNameStr withCmd:(NSString*) cmdStr withContent:(NSString*) contentStr{
    
    NSLog(@"-------callJsCCNodeFunc_3...");
    
    std::string funcName = [funcNameStr UTF8String];
    std::string param001 = [cmdStr UTF8String];
    std::string param002 = [contentStr UTF8String];

    std::string jsCallStr = cocos2d::StringUtils::format("cc.find('AppMain').getComponent('IOSCtrl').%s(\"%s\",\"%s\");", funcName.c_str(),param001.c_str(),param002.c_str());
    
    NSLog(@"--------- jsCallStr = %s", jsCallStr.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}




+(void)callJsGlobalFunc_1:(NSString*) funcNameStr{
    
    NSLog(@"-------callJsGlobalFunc_1...");
    
    std::string funcName = [funcNameStr UTF8String];
    std::string jsCallStr = cocos2d::StringUtils::format("%s();",funcName.c_str());
    NSLog(@"--------- jsCallStr = %s", jsCallStr.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}

+(void)callJsGlobalFunc_2:(NSString*) funcNameStr withCmd:(NSString*) cmdStr{
    
    NSLog(@"-------callJsGlobalFunc_2...");
    
    std::string funcName = [funcNameStr UTF8String];
    std::string param001 = [cmdStr UTF8String];
    std::string jsCallStr = cocos2d::StringUtils::format("%s(\"%s\");",funcName.c_str(), param001.c_str());
    NSLog(@"--------- jsCallStr = %s", jsCallStr.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}


+(void)callJsGlobalFunc_3:(NSString*) funcNameStr withCmd:(NSString*) cmdStr withContent:(NSString*) contentStr{
    NSLog(@"-------callJsGlobalFunc_3...");
    
    std::string funcName = [funcNameStr UTF8String];
    std::string param001 = [cmdStr UTF8String];
    std::string param002 = [contentStr UTF8String];
    std::string jsCallStr = cocos2d::StringUtils::format("%s(\"%s\",\"%s\");",funcName.c_str(), param001.c_str(),param002.c_str());
    NSLog(@"--------- jsCallStr = %s", jsCallStr.c_str());
//    ScriptingCore::getInstance()->evalString(jsCallStr.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}

@end

3.实现TS脚本:IOSCtrl.ts

到这里了,看下我的Cocos Creator 中的 ts 代码吧!脚本名字:IOSCtrl.ts

在这里我们定义了与 object-c 交互的函数。

代码如下:


const { ccclass, property } = cc._decorator;

/**
 * 这里是一个全局函数,函数名为 GetBigAward ,带有一个参数。
 * 可供 object-c 调用 js/ts 用。
 */
window["GetBigAward"] = function(code:string){
    console.error("------ object-c 调用 js 全局函数,参数 code = ",code);
}

/**
* 与 Ios object-c 交互
* 此脚本 绑定在 游戏中景中 AppMain 节点下,可以通过 cc.find('AppMain');语句找到此节点。
*/
@ccclass
export class IOSCtrl  extends cc.Component {
    onLoad(){
        console.log("------ IOSCtrl onLoad");
        // this.AddListener();
    }

    onDestroy(){
        // this.RemoveListener();
    }

    // private AddListener(){
    //     Messenger.AddListener(MsgEvent.CSJSDK_IOS_LookVideo,this.LookVideo,this);
    //     Messenger.AddListener(MsgEvent.CSJSDK_IOS_ShowBanner,this.ShowBanner,this);
    //     Messenger.AddListener(MsgEvent.CSJSDK_IOS_HideBanner,this.HideBanner,this);
    // }

    // private RemoveListener(){
    //     Messenger.RemoveListener(MsgEvent.CSJSDK_IOS_LookVideo,this.LookVideo,this);
    //     Messenger.RemoveListener(MsgEvent.CSJSDK_IOS_ShowBanner,this.ShowBanner,this);
    //     Messenger.RemoveListener(MsgEvent.CSJSDK_IOS_HideBanner,this.HideBanner,this);
    // }

    /**
     * js/ts 调用 object-c 用。
     */
    private LookVideo():void{
        if ('jsb' in window) {
            if (cc.sys.os == cc.sys.OS_IOS) {
                console.error("------- js 调用 object-c 去 看视频 ");
                // js 调用 object-c 中 AppController 类中的 静态函数 csjAdRewardOpen ,带有一个参数。
                // 注意 函数名必须带上 ":" ,否则无法找到 函数。 如 "csjAdRewardOpen:"
                jsb.reflection.callStaticMethod("AppController", "csjAdRewardOpen:","参数1");

                // 如果在 object-c 把函数定义成这个样子:+ (void)csjAdRewardOpen:(NSString *)code withcmd:(NSString *)code2; 
                // 那么调用时函数名必须写成 "csjAdRewardOpen:withcmd:"
                // jsb.reflection.callStaticMethod("AppController", "csjAdRewardOpen:withcmd:","参数1","参数2");
            }
        }
    }

    /**
     * js/ts 调用 object-c 用。
     */
    private ShowBanner():void{
        if ('jsb' in window) {
            if (cc.sys.os == cc.sys.OS_IOS) {
                console.error("------- js 调用 object-c 去 csjAdShowBanner ");
                jsb.reflection.callStaticMethod("AppController", "csjAdShowBanner:","2222");
            }
        }
    }

    /**
     * js/ts 调用 object-c 用。
     */
    protected HideBanner():void{
        if ('jsb' in window) {
            if (cc.sys.os == cc.sys.OS_IOS) {
                console.error("------- js 调用 object-c 去 csjAdHideBanner ");
                jsb.reflection.callStaticMethod("AppController", "csjAdHideBanner:","3333");
            }
        }
    }

    /**
     * 可供 object-c 调用 js/ts 用。
     */
    public GetAward(code:string){
        console.error("------ object-c 调用了 js 返回了视屏奖励,code =",code)
        // let mon = Platform.instance.platformHadler as CSJSDKPlatform;
        // if(mon){
        //     CSJSDKPlatform.IOSGetRewardVideo();
        // }
    }

    /**
     * 可供 object-c 调用 js/ts 用。
     * @param code 
     * @param code2 
     */
    public GetAward2(code:string,code2:string){
        console.error("------ object-c 调用了 js 返回了视屏奖励,code =",code,",code2 = ",code2)
        // let mon = Platform.instance.platformHadler as CSJSDKPlatform;
        // if(mon){
        //     CSJSDKPlatform.IOSGetRewardVideo();
        // }
    }
}

4.Object-C 如何调用 js/ts 。

 最后 Object-C 如何调用 js/ts 。

在 xCode 某个脚本中,定义并实现 testCallJs 函数。(例如可以在 AppController 脚本中,脚本中导入 CallJS.h 头文件 才可以调用 CallJS 中的函数)。

#import "CallJS.h"
- (void)testCallJs{
    // 调用 js/ts 脚本中的函数: AppMain 节点下 IOSCtrl 脚本中的 GetAward 的函数。
    [CallJS callJsCCNodeFunc_1:@"第1个参数!"];
    // 调用 js/ts 脚本中的函数: AppMain 节点下 IOSCtrl 脚本中的 GetAward2 的函数。
    [CallJS callJsCCNodeFunc_3:@"GetAward2" withCmd:@"第1个参数!" withContent:@"第2个参数!"];
    // 调用 js/ts 的全局函数:GetBigAward
    [CallJS callJsGlobalFunc_2:@"GetBigAward" withCmd:@"第1个参数!"];
}

再看 js/ts 如何调用 object-c

1.在object-c中实现供ts调用的函数。

在xcode 编辑器中。找到 AppController.h , AppController.m 脚本,分别添加一个静态函数(必须是静态函数)声名与定义。在这里添加函数工 js/ts 调用。

代码如下:

 AppController.h 中添加静态函数声明:

// 静态函数声明
+ (void)csjAdRewardOpen:(NSString *)code;
// 静态函数声明
+ (void)csjAdShowBanner:(NSString *)code;
// 静态函数声明
+ (void)csjAdHideBanner:(NSString *)code;

AppController.m 中添加静态函数实现:

+ (void)csjAdRewardOpen:(NSString *)code{
    NSLog(@"-------------------静态函数实现");
}

+ (void)csjAdShowBanner:(NSString *)code{
    NSLog(@"-------------------静态函数实现");
}

+ (void)csjAdHideBanner:(NSString *)code{
    NSLog(@"-------------------静态函数实现");
}

2. 在js/ts调用object-c函数。

其实在上面代码 IOSCtrl.ts 脚本中已经给出。这里就复制一份代码吧。

    /**
     * js/ts 调用 object-c 用。
     */
    private LookVideo():void{
        if ('jsb' in window) {
            if (cc.sys.os == cc.sys.OS_IOS) {
                console.error("------- js 调用 object-c 去 干事 ");
                // js 调用 object-c 中 AppController 类中的 静态函数 csjAdRewardOpen ,带有一个参数。
                // 注意 函数名必须带上 ":" ,否则无法找到 函数。 如 "csjAdRewardOpen:"
                jsb.reflection.callStaticMethod("AppController", "csjAdRewardOpen:","参数1");

                // 如果在 object-c 把函数定义成这个样子:+ (void)csjAdRewardOpen:(NSString *)code withcmd:(NSString *)code2; 
                // 那么调用时函数名必须写成 "csjAdRewardOpen:withcmd:"
                // jsb.reflection.callStaticMethod("AppController", "csjAdRewardOpen:withcmd:","参数1","参数2");
            }
        }
    }

结束

有关 cocos creator js/ts 与 object-c 的交互就写完了。

如有不懂,仔细阅读 cocos creator 文档。https://docs.cocos.com/creator/manual/zh/advanced-topics/oc-reflection.html

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值