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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章