南锋

南奔万里空,脱死锋镝余

Cocos Creator 3.x iOS 热更新成功后仍运行旧代码的解决方法

同一套 Cocos Creator 热更新逻辑在 Android 上工作正常,但移植到 iOS 后,热更新下载到 100% 并重启 App,启动后仍然执行旧代码。文件通常已经下载成功,真正的问题往往是 iOS 启动时没有恢复热更新目录的 searchPaths。

问题排查

检查 Cocos Creator 3.x 热更新目录

我这里指定的路径是 -s ${path.join(result.dest, resdir)}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
exports.onAfterBuild = function (options, result) {
let resdir = 'assets';

if (fs.existsSync(path.join(result.dest, 'data'))) {
resdir = 'data';
}
let cmd = `node version_generator.js -v ${game_version} -u https://lengmo714/${game_version}/ -s ${path.join(result.dest, resdir)} -d ${path.join(Editor.Project.path, "assets\\resources")}`

console.warn("热更地址:", cmd);

exec(cmd, { cwd: Editor.Project.path }, (err, stdout, stderr) => {
if (!err) return;
console.error(err);
});
}

iOS大概率是:

1
build/iOS/data

热更后本地路径一般类似:

1
Documents/asset

我这里就是没注意,在OC中改路径,导致路径不对。
Cocos Creator 3.x iOS 热更新成功后仍运行旧代码的解决方法 — 检查 Cocos Creator 3.x 热更新目录

改了路径后,路径就对了
Cocos Creator 3.x iOS 热更新成功后仍运行旧代码的解决方法 — 检查 Cocos Creator 3.x 热更新目录

重点:App 重启后恢复 searchPaths

上面路径改了之后问题依然存在,说明没有找到问题的本质原因
关键问题在于

1
2
3
4
5
6
7
8
9
10
11
this._am.setEventCallback(null!);
this._updateListener = null;
var searchPaths = jsb.fileUtils.getSearchPaths();
var newPaths = this._am.getLocalManifest().getSearchPaths();
console.log("---- newPaths", JSON.stringify(newPaths));
Array.prototype.unshift.apply(searchPaths, newPaths);
localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
jsb.fileUtils.setSearchPaths(searchPaths);
setTimeout(() => {
game.restart();
}, 100)

我这里只在热更完成后setSearchPaths。但是重启后,没有在游戏入口最早的位置重新setSearchPaths。所以iOS依旧走了旧代码。
最简单的方法,在main.js中改成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
window.self = window;
require("src/system.bundle.js");
// 新增代码
const jsb = window['jsb'];
if (jsb && jsb.fileUtils) {
const hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths');
if (hotUpdateSearchPaths) {
const paths = JSON.parse(hotUpdateSearchPaths);
jsb.fileUtils.setSearchPaths(paths);
console.log("--- restore HotUpdateSearchPaths:", paths);
}
}
// 下面是导出生成的代码

const importMapJson = jsb.fileUtils.getStringFromFile("src/import-map.json");
const importMap = JSON.parse(importMapJson);
System.warmup({
importMap,
importMapUrl: 'src/import-map.json',
defaultHandler: (urlNoSchema) => {
require(urlNoSchema.startsWith('/') ? urlNoSchema.substr(1) : urlNoSchema);
},
});

System.import('./src/application.js')
.then(({ Application }) => {
return new Application();
}).then((application) => {
return System.import('cc').then((cc) => {
require('jsb-adapter/engine-adapter.js');
return application.init(cc);
}).then(() => {
return application.start();
});
}).catch((err) => {
console.error(err.toString() + ', stack: ' + err.stack);
});

只需要修改上面两个地方就可以啦