使用OCRunner开发补丁的工作流.
OCRunner与JSPatch,OCEval和MangoFix等的主要区别:
-
下发二进制补丁文件。增加安全性,减小补丁大小,省去词法分析与语法分析,优化启动时间,可在PatchGenerator阶段进行优化(TODO: 未被调用的函数等信息,将会被过滤)
-
自定义的Arm64 ABI (可以不使用libffi)
-
完整的Objective-C语法支持,除去预编译和部分语法
本地使用OCRunner运行补丁
OCRunnerDemo可以作为整个流程的参照.
1. Cocoapods导入OCRunner
pod 'OCRunner' #支持所有架构,包含libffi.a
# 或者
pod 'OCRunnerArm64' #仅支持 arm64和arm64e,没有libffi.a
2. 下载 PatchGenerator
解压PatchGenerato.zip,然后将PatchGenerator保存到/usr/bin/或项目目录下.
3. 添加PatchGenerator的 Run Script
-
Project Setting -> Build Phases -> 左上角的
+
->New Run Script Phase
-
PatchGenerator的路径 -files Objective-C源文件列表或者文件夹 -refs Objective-C头文件列表或者文件夹 -output 输出补丁保存的位置
-
比如OCRunnerDemo中的
Run Script
$SRCROOT/OCRunnerDemo/PatchGenerator -files $SRCROOT/OCRunnerDemo/ViewController1 -refs $SRCROOT/OCRunnerDemo/Scripts.bundle -output $SRCROOT/OCRunnerDemo/binarypatch
4. 开发环境下: 运行补丁
-
将生成的补丁文件作为资源文件添加到项目中
-
Appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#if DEBUG
NSString *patchFilePath = [[NSBundle mainBundle] pathForResource:@"PatchFileName" ofType:nil];
#else
// download from server
#endif
[ORInterpreter excuteBinaryPatchFile:patchFilePath];
return YES;
}
- 每次修改文件,记得Command+B,调用Run Scrip,重新生成补丁文件.
5. 正式环境
- 将补丁上传到服务器
- App中下载补丁文件并保存到本地
- 使用**[ORInterpreter excuteBinaryPatchFile:PatchFilePath]** 执行补丁
使用介绍
1. 引入结构体、枚举、typedef
可以通过修改OCRunnerDemo中的ViewController1,运行以下代码.
// 将添加一个名为dispatch_once_t的新类型
typedef NSInteger dispatch_once_t;
// link NSLog
void NSLog(NSString *format, ...);
typedef enum: NSUInteger{
UIControlEventTouchDown = 1 << 0,
UIControlEventTouchDownRepeat = 1 << 1,
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4
}UIControlEvents;
int main(){
UIControlEvents events = UIControlEventTouchDown | UIControlEventTouchDownRepeat;
if (events & UIControlEventTouchDown){
NSLog(@"UIControlEventTouchDown");
}
NSLog(@"enum test: %lu",events);
return events;
}
main();
Tips:
推荐新建一个文件来放置以上代码,类似于OCRunnerDemo中的UIKitRefrence和GCDRefrence文件,然后使用PatchGenerator以**-links**的形式加入补丁生成。作者想偷偷懒,不想再去CV了,头文件太多了😭.
2. 使用系统内置C函数
//you only need to add the C function declaration in Script.
//link NSLog
void NSLog(NSString *format, ...);
//then you can use it in Scrtips.
NSLog(@"test for link function %@", @"xixi");
当你运行以上代码时. OCRunner将会使用ORSearchedFunction
搜索函数的指针.
这个过程的核心实现是 SymbolSearch
(修改自fishhook
).
如果搜索到的结果是NULL,OCRunner将会自动在控制台打印如下信息:
|----------------------------------------------|
|❕you need add ⬇️ code in the application file |
|----------------------------------------------|
[ORSystemFunctionTable reg:@"dispatch_source_set_timer" pointer:&dispatch_source_set_timer];
3. 修复OC对象(类)方法、添加属性
小天才英语学习机,不会哪里点哪里
想修复哪个方法,将改方法实现即可,不用实现其他方法.
@interface ORTestClassProperty:NSObject
@property (nonatomic,copy)NSString *strTypeProperty;
@property (nonatomic,weak)id weakObjectProperty;
@end
@implementation ORTestClassProperty
- (void)otherMethod{
self.strTypeProperty = @"Mango";
}
- (NSString *)testObjectPropertyTest{
[self otherMethod];
return self.strTypeProperty;
}
@end
4.Block使用、循环引用解决
// 用于解决循环引用
__weak id object = [NSObject new];
// 最简block声明
void (^a)(void) = ^{
int b = 0;
};
a();
更新了GitPage,但是没提交md源文件,只能回家以后才能更新掘金了😂.