好久没发文了,最近在编写tweak时,因为weak.xm没有代码提醒,着实痛苦,所以写了个脚本方便利用xcode在tweak.m中书写代码,通过自定义脚本预编译成tweak.xm再使用theos正常编译。在xcode中目录结构如下:
多出四个文件(注意tweak.xm完全为自动生成,不要手写代码):
1、Tweak.h 空文件,真的什么都没有。
2、TweakDefine.h 宏定义%hook、%end、%new、%orig等tweak专有符号。
3、Tweak.m tweak.xm的替代品,执行完 python3 run.py 后生成tweak.xm。
4、run.py tweak.m到tweak.xm的转换器,可根据需要自行编辑。与TweakDefine.h中定义的宏一一对应即可。
TweakDefine.h:
#ifndef TweakDefine_h
#define TweakDefine_h
#import "Tweak.h"
#define orig_method @""
#define new_method
#define hook_class
#endif /* TweakDefine_h */
Tweak.m:
#import "Tweak.h"
#import "TweakDefine.h"
#endif /* TweakDefine_h */
@interface AnyObject : NSObject
@end
/*
添加hook_class 表示需要hook的类,不添加则默认为自定义类。
*/
hook_class
@implementation AnyObject
/*
定义新方法
*
new_method
- (void)newMethod {
}
/*
需要hook的方法
*
- (void)beHookedMethod {
//回调原方法
orig_method;
}
@end
run.py:
# -*- coding: utf-8 -*-
import os
treak_m = './Tweak.m'
treak_xm = './Tweak.xm'
def replace_end(text):
chips = text.split('@end')
text = ''
for chip in chips:
if chip.replace('\n', '').replace(' ', '') != '':
if 'hook_class\n@implementation' in chip:
print('<<<<' + chip + '>>>>>>')
text = text + chip + '%end'
else:
print('[[[[[[' + chip + ']]]]]]')
text = text + chip + '@end'
return text
def pre_compile():
old_text = None
with open(treak_m,"r+") as fr:
old_text = fr.read()
print(old_text)
text = replace_end(old_text)
text = text.replace('hook_class\n@implementation', '%hook')\
.replace('orig_method', '%orig')\
.replace('new_method', '%new')\
.replace('#import "Tweak.h"', '')\
.replace('#import "TweakDefine.h"', '')
with open(treak_xm,"w+") as fw:
fw_new = fw.write(text)
print('=========')
print(fw_new)
pre_compile()
os.system('make package install')
额外记录一段常用代码方便把NSLog打印的数据存储到沙盒:
@interface XXXAppDelegate : NSObject
- (void)redirectNSLogToDucumentFile;
@end
hook_class
@implementation XXXAppDelegate
- (_Bool)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2
{
[self redirectNSLogToDucumentFile];
return orig_method;
}
new_method
- (void)redirectNSLogToDucumentFile{
//创建文件路径
NSString *documentpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [NSString stringWithFormat:@"%@.log",[NSDate date]];
fileName = [fileName stringByReplacingOccurrencesOfString:@" " withString:@"-"];
NSString *logFilePath = [documentpath stringByAppendingPathComponent:fileName];
//删除已经存在文件
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:logFilePath error:nil];
//log写入
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
NSLog(@"\n******************************\n** **\n** 开始打印日志 **\n** **\n******************************\n");
}
@end