前言
上期讲了ts与android的交互,今天讲讲cocos与ios的交互与自动化
ts -> ios
ts发起调用
在TestNativePlugin.ts的start里发起调用
jsb.reflection.callStaticMethod(
'APIObject',
'sendMsgToPlugin:',
'test');
参数的意思:
'APIObject': 指的我们编写的OC类:api.mm文件里的APIObject类
'sendMsgToPlugin:': 因为是callStaticMethod,所以是APIObject的静态方法(注意带冒号)
'test': 传递给sendMsgToPlugin的实参
总结:
相当于调用OC的APIObject类的 APIObject.sendMsgToPlugin('test')
ios处理函数
在项目根目录下按照build路径添加api.mm和api.h:
cocos_learn\build-templates\
jsb-link\frameworks\runtime-src\proj.ios_mac\ios\
api.mm
之所以要在build-templates目录下按build结构添加文件,是因为creator build的时候会把这个目录下的文件拷贝到构建目录去,这样我们就不用手动处理了。
然后编写api.h和api.mm测试:
#import "api.h"
#import
#import "platform/CCApplication.h"
#import "scripting/js-bindings/jswrapper/SeApi.h"
#import "base/CCScheduler.h"
#import "string.h"
@interface APIObject : NSObject
+(void) sendMsgToPlugin:(NSString*)msg;
@end
@implementation APIObject
+(void) sendMsgToPlugin:(NSString *)msg {
NSLog(msg);
if ([msg isEqualToString:@"test"]) {
// 显示弹框
UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"标题" message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureBtn = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"确定");
sendMsgToEngine("test_ok;ios", true);
}];
[alertVc addAction :sureBtn];
UIWindow *window = [[UIApplication sharedApplication].delegate window];
UIViewController *topViewController = [window rootViewController];
[topViewController presentViewController:alertVc animated:YES completion:nil];
}
}
@end
代码解读: 当收到的消息是'test'时,显示弹框。
实际应用中可将s按JSON解析,然后调用对应的模块去处理,或者直接转发消息出去,这里不再延伸。
我在TestNativePlugin.ts的start里发起调用,这样app一启动就会弹框提示。
ios -> ts
ios发起调用
ios执行后,需要向ts返回结果。
继续上面的例子,在ios.mm里添加:
extern "C" {
void sendMsgToEngine(const char *msg, bool async) {
if (!async) {
std::string s = "window.__native('";
s += msg;
s += "')";
se::ScriptEngine::getInstance()->evalString(s.c_str());
} else {
Application::getInstance()->getScheduler()->performFunctionInCocosThread([=](){
sendMsgToEngine(msg, false);
});
}
}
}
总结:
相当于调用ts:
window.__native(msg)
注意:上面区分了同步和异步,保险的话都走异步即可,只是有时候需要同步获得返回结果则需要同步。
上面的例子是在用户点击确定后调用(返回引擎):
sendMsgToEngine("test_ok;ios", true);
ts处理函数
在TestNativePlugin.ts的onLoad设置处理函数:
onLoad () {
let w = window as any;
w.__native = (s:string)=>{
cc.log('native msg:', s);
let arr = s.split(';');
let type = arr[0];
if (type == 'test_ok') {
this.label.string = 'test ok:' + arr[1];
}
};
}
代码解读: 将收到的消息按分号拆分,参数1是'test_ok'时,label显示第2个参数。
这时运行app,会弹出确定框,点击确定后会显示:
test ok: ios
自动化
xcode自动导入源文件及framework
在build-templates下按build路径存放文件,在build后会被自动拷贝过去。
但xcode工程并没有使用我们的文件,所以需要我们修改xcodeproj文件。
目前我找到的是ruby的xcodeproj方案,如果以后nodejs有xcodeproj的方案就更方便了。
在mac上安装ruby及其xcodeproj库我就省略了,具体可以看下网上的帖子:https://www.jianshu.com/p/cca701e1d87c
具体思路:
1.编写插件,处理编辑器消息'before-change-files'
load () {
// execute when package loaded
this.onBeforeBuildFinish = this.onBeforeBuildFinish.bind(this);
Editor.Builder.on('before-change-files', this.onBeforeBuildFinish);
},
unload () {
// execute when package unloaded
Editor.Builder.removeListener('before-change-files', this.onBeforeBuildFinish);
},
2.判断是ios平台,则调用make_xcodeproj.rb脚本生成xcodeproj文件
onBeforeBuildFinish(options, callback) {
Editor.log('Building ' + options.platform + ' to ' + options.dest);
if (options.platform == 'ios') {
this.makeXcodeProj(options);
}
callback();
},
makeXcodeProj(options) {
let root = options.dest;
let projName = options.title;
let proj = root + `/frameworks/runtime-src/proj.ios_mac/${projName}.xcodeproj`;
Editor.log('make xcodeproj: ' + proj);
try {
let script = __dirname + '/make_xcodeproj.rb';
let cmd = `ruby ${script} ${proj}`;
let ret = child_process.execSync(cmd);
// console.log(ret);
} catch (e) {
Editor.error(`cmd error: ${e.message}`);
return false;
}
}
3.make_xcodeproj.rb脚本里添加api.mm、NativePlugin.framework(此framework仅用于测试导入)
# #向group中增加文件引用(.h文件只需引用一下,.m引用后还需add一下)
file_ref = group.new_reference('./ios/api.h')
file_ref = group.new_reference('./ios/api.mm')
target.add_file_references([file_ref])
#通过xcodeproj在工程中引入framwork、.a文件和bundle文件
#添加xx.framework的引用
file_ref = project.frameworks_group.new_file('./ios/NativePlugin.framework')
target.frameworks_build_phases.add_file_reference(file_ref)
这样creator构建后,脚本就自动将我们写的mm文件、framework文件添加到xcode工程了,然后用xcode打开运行即可,不用每次手动添加了。
后语
好了,今天就讲到这儿了,喜欢的朋友关注或转发一下,谢谢!
ps: 点击阅读原文可查看本文源码。