选择技术实现方案
近段时间,由于公司要求需要增加热更新或热修复功能,这个开发需求让我有点头疼。记忆中苹果公司已于2017年3月禁止了JSPatch那种方式的热更新,我只好放弃JSPatch这种方案。网上找了一圈,只有TTPatch和MangoFix这两个框架可行,但这两个框架目前都不支持swift语言开发的项目。由于我手上的公司项目代码还是OC开发的项目,不影响使用这两个框架。TTPatch是JSPatch的简化版,原理与JSPatch相似。MangoFix是DSL(即领域专用语言)开发的,性能比TTPatch高出好几倍。对比这两个框架后,我选择了MangoFix,其实最主要的原因是MangoFix可以无感进行修复代码,用户不用下载补丁文件操作,只需要配置更新文件的远程地址将更新文件保存在本地即可。另外,据MangoFix的作者说,MangoFix2.0版本将支持swift语言,我们一起期待吧!
更新于12月1日
目前已经从MangoFix升级到OCRunner,OCRunner可以支持方法以dynamic @objc开头的Swift文件热修复。相比MangoFix支持的方法更多了。参考以下链接文档
https://github.com/SilverFruity/OCRunner/blob/master/README-CN.md
码云储存补丁配置远程地址
首先,新建一个码云仓库的公开开源项目,记得不要建私有项目,这样会导致访问不了文件的问题出现。
然后,将mg后缀的补丁文件上传上去即可。
最后,我们需要知道补丁文件的远程地址。怎么从码云那里获取到远程地址呢?可以从以下截图获得
info.png
MangoFix使用方法
MangoFix的具体使用请参照GitHub上的说明,请点击查看(Mango/README-CN.md at master · YPLiang19/Mango (github.com)
)。
其实最重要的是将MangoFix打包下载下来,打开MangoFixDemo文件夹里面的Demo。想使用远程地址替换本地的更新需要将下面代码进行设置:
#pragma mark - 热修复
- (BOOL)encryptPlainScirptToDocument{
NSError *outErr = nil;
BOOL writeResult = NO;
//本地
// NSURL *scriptUrl = [[NSBundle mainBundle] URLForResource:@"xxxPatch" withExtension:@"mg"];
//远程
NSDictionary *info= [[NSBundle mainBundle] infoDictionary];
NSString *BundleVersion = info[@"CFBundleShortVersionString"];
NSString *pathStr = [NSString stringWithFormat:@"https://gitee.com/xxx/xx-patch/raw/master/xxxPatch%@.mg",BundleVersion];
#ifdef DEBUG
pathStr = @"https://gitee.com/xxx/xx-patch/raw/master/xxxPatchTest.mg";
#else
#endif
NSURL *scriptUrl = [NSURL URLWithString:pathStr];
NSString *plainScriptString = [NSString stringWithContentsOfURL:scriptUrl encoding:NSUTF8StringEncoding error:&outErr];
if (outErr) goto err;
{
NSURL *publicKeyUrl = [[NSBundle mainBundle] URLForResource:@"public_key.txt" withExtension:nil];
NSString *publicKey = [NSString stringWithContentsOfURL:publicKeyUrl encoding:NSUTF8StringEncoding error:&outErr];
if (outErr) goto err;
NSString *encryptedScriptString = [MFRSA encryptString:plainScriptString publicKey:publicKey];
NSString * encryptedPath= [(NSString *)[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"encrypted_xxxPatch.mg"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:encryptedPath]) {
[fileManager createFileAtPath:encryptedPath contents:nil attributes:nil];
}
writeResult = [encryptedScriptString writeToFile:encryptedPath atomically:YES encoding:NSUTF8StringEncoding error:&outErr];
}
err:
if (outErr) NSLog(@"%@",outErr);
return writeResult;
}
总结
OK,以上几步完成基本就可以实现热更新了,具体的测试案例可以参照MangoFixDemo里面的案例。
参考资料如下:
[MangoFix中文资料](Mango/README-CN.md at master · YPLiang19/Mango (github.com)
)
[iOS热更新方案](iOS 现在的 “热修复/热更新” - 简书 (jianshu.com)
)
网友评论