├── .gitignore
├── Makefile
├── README.md
├── ShortcutToDebug.plist
├── SpringBoard.h
├── Tap2DebugRootless.png
├── TapSB.x
├── Tweak.x
├── common.h
├── control
├── resource
├── Dopamine2.0.8.ipa
└── Filza.ipa
└── xia0.h
/.gitignore:
--------------------------------------------------------------------------------
1 | .theos/
2 | packages/
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | GO_EASY_ON_ME = 1
2 | THEOS_DEVICE_IP = localhost -o StrictHostKeyChecking=no
3 | THEOS_DEVICE_PORT = 2222
4 | ARCHS = arm64 arm64e
5 | TARGET := iphone:clang:latest:15.0
6 |
7 | THEOS_PACKAGE_SCHEME=rootless
8 | THEOS_PACKAGE_INSTALL_PREFIX=/var/jb
9 |
10 | INSTALL_TARGET_PROCESSES = SpringBoard
11 |
12 | include $(THEOS)/makefiles/common.mk
13 |
14 | TWEAK_NAME = ShortcutToDebug
15 |
16 | ShortcutToDebug_FILES = Tweak.x TapSB.x
17 | ShortcutToDebug_CFLAGS = -fobjc-arc
18 |
19 | include $(THEOS_MAKE_PATH)/tweak.mk
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tap2DebugRootless
2 | 基于 Dopamine 无根越狱实现的插件,该插件可以通过使用 3D Touch 快速 Debug 调试某个 App
3 |
4 | #### Screenshots
5 |
6 |
7 |
8 | #### Install
9 |
10 | ##### 准备:
11 |
12 | - 安装巨魔 (https://ios.cfw.guide/installing-trollstore/)
13 | - 通过巨魔安装`resource`里的`Dopamine2.0.8`并执行越狱操作
14 |
15 | - 通过巨魔安装`resource`里的`Filza`
16 | - 安装`Theos`环境 (参考文章`https://cloud.tencent.com/developer/article/2007333`)
17 |
18 | ##### 方式一:自主编译
19 |
20 | - ```shell
21 | https://github.com/DargonLee/Tap2DebugRootless.git
22 | ```
23 |
24 | - ```
25 | cd Tap2DebugRootless
26 | ```
27 |
28 | - ```shell
29 | make clean && make && make package
30 | ```
31 |
32 | - 拷贝`packages`文件夹下的`deb`文件到`Filza`的某个目录,然后点击安装
33 |
34 | - 安装成功后打开`Dopamine`重启用户空间就可以正常使用了
35 |
36 | ##### 方式二:直接安装
37 |
38 | - 下载Release包
39 | - 拷贝`deb`文件到`Filza`的某个目录,然后点击安装
40 | - 安装成功后打开`Dopamine`重启用户空间就可以正常使用了
41 |
42 | #### Usage
43 |
44 | - 长按要调试的 App 选择`Tap2Debug`
45 |
46 | - 点击`Attach`
47 |
48 | - 然后点击打开 App
49 |
50 | - 在 Mac 设备上打开终端输入`lldb`
51 |
52 | - ```shell
53 | (lldb) process connect connect://192.168.12.76:20221
54 | ```
55 |
56 | - 192.168.12.76 是你手机的 ip 地址
57 |
58 | #### Credit
59 |
60 | - [4ch12dy/Tap2Debug: tap shortcut(double tap app icon is deault close because app will pause) to debug app (support iOS11/12/13 and A12) (github.com)](https://github.com/4ch12dy/Tap2Debug)
61 | - [SpringBoard tweak 双击图标启动debugserver - 干货分享 - 睿论坛 (iosre.com)](https://iosre.com/t/springboard-tweak-双击图标启动debugserver/16420)
62 |
--------------------------------------------------------------------------------
/ShortcutToDebug.plist:
--------------------------------------------------------------------------------
1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; }
2 |
--------------------------------------------------------------------------------
/SpringBoard.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RBSProcessIdentity : NSObject
4 | @property(readonly, copy, nonatomic) NSString *executablePath;
5 | @property(readonly, copy, nonatomic) NSString *embeddedApplicationIdentifier;
6 | @end
7 |
8 | @interface FBProcessExecutionContext : NSObject
9 | @property (nonatomic,copy) NSDictionary* environment;
10 | @property (nonatomic,copy) RBSProcessIdentity* identity;
11 | @end
12 |
13 | @interface FBProcessManager : NSObject
14 | - (void)handleSafeModeForExecutionContext:(FBProcessExecutionContext*)executionContext withApplicationID:(NSString*)applicationID;
15 | @end
16 |
17 |
18 |
19 | @interface SBApplicationInfo : NSObject
20 | @property (nonatomic,readonly) NSURL* executableURL;
21 | @property (nonatomic,readonly) BOOL hasHiddenTag;
22 | @property (nonatomic,retain,readonly) NSArray* tags;
23 | @end
24 |
25 | @interface SBApplication : NSObject
26 | - (SBApplicationInfo*)_appInfo;
27 | @end
28 |
29 | @interface SBSApplicationShortcutIcon : NSObject
30 | @end
31 |
32 | @interface SBSApplicationShortcutSystemItem : SBSApplicationShortcutIcon
33 | - (instancetype)initWithSystemImageName:(NSString*)systemImageName;
34 | @end
35 |
36 | @interface SBSApplicationShortcutItem : NSObject
37 | @property (nonatomic,copy) NSString* type;
38 | @property (nonatomic,copy) NSString* localizedTitle;
39 | @property (nonatomic,copy) NSString* localizedSubtitle;
40 | @property (nonatomic,copy) SBSApplicationShortcutIcon* icon;
41 | @property (nonatomic,copy) NSDictionary* userInfo;
42 | @property (assign,nonatomic) NSUInteger activationMode;
43 | @property (nonatomic,copy) NSString* bundleIdentifierToLaunch;
44 | @end
45 |
46 | @interface SBIconView : NSObject
47 | - (NSString*)applicationBundleIdentifier;
48 | - (NSString*)applicationBundleIdentifierForShortcuts;
49 | @end
50 |
51 | @interface SBUIAppIconForceTouchControllerDataProvider : NSObject
52 | - (NSString*)applicationBundleIdentifier;
53 | @end
54 |
55 | @interface SBIconController : NSObject
56 | @property (weak, nonatomic) id _rootFolderController;
57 | @end
58 |
59 | @interface SBUIAppIconForceTouchController : NSObject
60 | @property (weak, nonatomic) SBIconController* delegate;
61 | - (void) dismissAnimated:(BOOL)arg1 withCompletionHandler:(void (^)())block;
62 | @end
--------------------------------------------------------------------------------
/Tap2DebugRootless.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DargonLee/Tap2DebugRootless/9f1cead507f0adc39f5f96ba41891863001e7864/Tap2DebugRootless.png
--------------------------------------------------------------------------------
/TapSB.x:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "SpringBoard.h"
4 | #import "xia0.h"
5 | #import "common.h"
6 |
7 |
8 | NSString* toggleOneTimeApplicationID;
9 | #ifndef kCFCoreFoundationVersionNumber_iOS_11_0
10 | #define kCFCoreFoundationVersionNumber_iOS_11_0 1443.00
11 | #endif
12 |
13 | #ifndef kCFCoreFoundationVersionNumber_iOS_13_0
14 | #define kCFCoreFoundationVersionNumber_iOS_13_0 1665.15
15 | #endif
16 |
17 | %group iOS10Down
18 | %hook SBApplication
19 |
20 | - (id)valueForKeyPath:(NSString*)keyPath
21 | {
22 | if([keyPath isEqualToString:@"info.xia0_hasHiddenTag"])
23 | {
24 | return [[self _appInfo] valueForKey:@"xia0_hasHiddenTag"];
25 | }
26 |
27 | return %orig;
28 | }
29 |
30 | %end
31 | %end
32 |
33 | %group Shortcut_iOS13Up
34 |
35 | %hook SBIconView
36 |
37 | - (NSArray *)applicationShortcutItems
38 | {
39 | NSArray* orig = %orig;
40 |
41 | NSString* applicationID;
42 | if([self respondsToSelector:@selector(applicationBundleIdentifier)])
43 | {
44 | applicationID = [self applicationBundleIdentifier];
45 | }
46 | else if([self respondsToSelector:@selector(applicationBundleIdentifierForShortcuts)])
47 | {
48 | applicationID = [self applicationBundleIdentifierForShortcuts];
49 | }
50 |
51 | if(!applicationID)
52 | {
53 | return orig;
54 | }
55 |
56 |
57 | SBSApplicationShortcutItem* toggleSafeModeOnceItem = [[%c(SBSApplicationShortcutItem) alloc] init];
58 |
59 | toggleSafeModeOnceItem.localizedTitle = @"Tap2Debug";
60 |
61 |
62 | //toggleSafeModeOnceItem.icon = [[%c(SBSApplicationShortcutSystemItem) alloc] initWithSystemImageName:@"fx"];
63 | toggleSafeModeOnceItem.bundleIdentifierToLaunch = applicationID;
64 | toggleSafeModeOnceItem.type = @"com.xia0.tap2debug";
65 |
66 | return [orig arrayByAddingObject:toggleSafeModeOnceItem];
67 |
68 | return orig;
69 | }
70 |
71 | + (void)activateShortcut:(SBSApplicationShortcutItem*)item withBundleIdentifier:(NSString*)bundleID forIconView:(id)iconView
72 | {
73 | if(![item.type isEqualToString:@"com.xia0.tap2debug"]){
74 | return %orig;
75 | }
76 |
77 | XLOG("bundleID:%@ view:%@", bundleID, iconView);
78 | GCD_AFTER_MAIN(0.01)
79 | show_debug_view([iconView findViewController], bundleID);
80 | GCD_END
81 | }
82 |
83 | %end
84 |
85 | %end
86 |
87 | %group Shortcut_iOS12Down
88 |
89 | %hook SBUIAppIconForceTouchControllerDataProvider
90 |
91 | - (NSArray *)applicationShortcutItems
92 | {
93 | NSArray* orig = %orig;
94 |
95 | NSString* applicationID = [self applicationBundleIdentifier];
96 |
97 | if(!applicationID)
98 | {
99 | return orig;
100 | }
101 |
102 |
103 | SBSApplicationShortcutItem* toggleSafeModeOnceItem = [[%c(SBSApplicationShortcutItem) alloc] init];
104 |
105 | toggleSafeModeOnceItem.localizedTitle = @"ShortcutToDebug";
106 |
107 | //toggleSafeModeOnceItem.icon = [[%c(SBSApplicationShortcutSystemItem) alloc] init];
108 | toggleSafeModeOnceItem.bundleIdentifierToLaunch = applicationID;
109 | toggleSafeModeOnceItem.type = @"com.xia0.tap2debug";
110 |
111 | if(!orig)
112 | {
113 | return @[toggleSafeModeOnceItem];
114 | }
115 | else
116 | {
117 | return [orig arrayByAddingObject:toggleSafeModeOnceItem];
118 | }
119 |
120 | return orig;
121 | }
122 |
123 | %end
124 |
125 | %hook SBUIAppIconForceTouchController
126 |
127 | - (void)appIconForceTouchShortcutViewController:(id)arg1 activateApplicationShortcutItem:(SBSApplicationShortcutItem*)item
128 | {
129 | if(![item.type isEqualToString:@"com.xia0.tap2debug"]){
130 | return %orig;
131 | }
132 |
133 | NSString* bundleID = item.bundleIdentifierToLaunch;
134 | // Ivar ivar = object_getInstanceVariable(object_getClass(self.delegate), "_rootFolderController", NULL);
135 | // id rootFolderController = (__bridge id)((__bridge void *)self.delegate + ivar_getOffset(ivar));
136 | // id rootFolderController = MSHookIvar(self.delegate, "_rootFolderController");
137 | SBIconController* sbivc = self.delegate;
138 | id rootFolderController = sbivc._rootFolderController;
139 | XLOG(@"tap on app:%@ vc:%@ rootFolderController:%@", bundleID, arg1, rootFolderController);
140 | [self dismissAnimated:YES withCompletionHandler:^{
141 | GCD_AFTER_MAIN(0.01)
142 | show_debug_view(rootFolderController, bundleID);
143 | GCD_END
144 | }];
145 | }
146 |
147 | %end
148 |
149 | %end
150 |
151 | %ctor
152 | {
153 | %init();
154 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0)
155 | {
156 | // %init(SafeMode_iOS13Up);
157 | %init(Shortcut_iOS13Up);
158 | }
159 | else
160 | {
161 | // %init(SafeMode_iOS12Down);
162 | %init(Shortcut_iOS12Down);
163 | }
164 |
165 | if(kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_11_0)
166 | {
167 | %init(iOS10Down);
168 | }
169 | }
--------------------------------------------------------------------------------
/Tweak.x:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | #import "xia0.h"
5 | #import "common.h"
6 |
7 | @interface NSTask : NSObject
8 |
9 | - (id)init;
10 | - (void)setLaunchPath:(NSString *)path;
11 | - (void)setArguments:(NSArray *)arguments;
12 | - (void)launch;
13 | - (int)processIdentifier;
14 |
15 | @end
16 |
17 | @interface LSApplicationProxy : NSObject
18 | + (id) applicationProxyForIdentifier:(id)arg1;
19 | @property (readonly, nonatomic) NSString* canonicalExecutablePath;
20 | @end
21 |
22 | @interface TaskManager : NSObject
23 | + (TaskManager*)sharedManager;
24 | @property (nonatomic,strong) NSTask * runningTask;
25 | @end
26 |
27 | @implementation TaskManager
28 | + (TaskManager*)sharedManager {
29 | static TaskManager *_sharedSingleton = nil;
30 | static dispatch_once_t onceToken;
31 | dispatch_once(&onceToken, ^{
32 | _sharedSingleton = [[self alloc] init];
33 | });
34 | return _sharedSingleton;
35 | }
36 | @end
37 |
38 | @interface SBApplication : NSObject
39 | @property(copy, nonatomic) NSArray *dynamicShortcutItems;
40 | @property(copy, nonatomic) NSArray *staticShortcutItems;
41 | @property(copy, nonatomic) NSString* bundleIdentifier;
42 | - (id)badgeNumberOrString;
43 | - (void)loadStaticShortcutItemsFromInfoDictionary:(id)arg1 bundle:(id)arg2;
44 | - (NSString*)bundleIdentifier;
45 | - (NSString*)displayName;
46 | @end;
47 |
48 | @interface SBIcon : NSObject
49 | @property(copy, nonatomic) SBApplication* application;
50 | - (void)launchFromLocation:(int)location;
51 | - (BOOL)isFolderIcon;
52 | - (id)badgeNumberOrString;
53 | @end
54 |
55 | @interface SBIconView : UIView
56 |
57 | @property(nullable, nonatomic,copy) NSArray *gestureRecognizers;
58 | @property(nonatomic,copy) NSString *applicationBundleIdentifierForShortcuts;
59 | @property(nonatomic,copy) SBIcon *icon;
60 | @end
61 |
62 | void show_debug_process_view(UIViewController* showVC, NSString* _bundleid, NSString* _attachModel) {
63 | NSString* bundle = _bundleid;
64 | if(!bundle){
65 | XLOG(@"error bundleid is null");
66 | return;
67 | }
68 | UIViewController *vc = showVC;
69 |
70 | NSString *debugserver = @"/var/jb/bin/debugserver";
71 | NSString *ip_port = @"0.0.0.0:1234";
72 | NSString *last_server = [[NSUserDefaults standardUserDefaults] objectForKey:@"server_bin_path"] ;
73 | NSString *last_ip =[[NSUserDefaults standardUserDefaults] objectForKey:@"ip_port"] ;
74 | if(last_server!=nil){
75 | debugserver = last_server;
76 | }
77 | if(last_ip != nil){
78 | ip_port = last_ip;
79 | }
80 |
81 | Class LSApplicationProxy_class = objc_getClass("LSApplicationProxy");
82 | NSObject *proxyObj = [LSApplicationProxy_class performSelector:@selector(applicationProxyForIdentifier:) withObject:bundle];
83 | NSString *canonicalExecutablePath = [proxyObj performSelector:@selector(canonicalExecutablePath)];
84 |
85 | UIAlertController *panel = [UIAlertController alertControllerWithTitle:@"🍎 SERVER LAUNCHER" message:canonicalExecutablePath preferredStyle:UIAlertControllerStyleAlert];
86 |
87 | [panel addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
88 | textField.userInteractionEnabled = NO;
89 | textField.placeholder = @"server path(not null)";
90 | textField.text = debugserver;
91 | GCD_AFTER_MAIN(0.3)
92 | textField.userInteractionEnabled = YES;
93 | GCD_END
94 | }];
95 | if ([_attachModel isEqualToString:@"Spawn"]) {
96 | [panel addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
97 | textField.placeholder = @"-x auto";
98 | textField.text = @"-x auto";
99 | textField.enabled = NO;
100 | textField.textColor = [UIColor lightGrayColor];
101 | }];
102 | }
103 | [panel addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
104 | textField.placeholder = @"ip:port(nullable)";
105 | textField.text = ip_port;
106 | }];
107 | if ([_attachModel isEqualToString:@"Attach"]) {
108 | [panel addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
109 | textField.placeholder = @"-a";
110 | textField.text = @"-a";
111 | textField.enabled = NO;
112 | textField.textColor = [UIColor lightGrayColor];
113 | }];
114 | }
115 |
116 | [panel addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
117 | textField.placeholder = @"executable path(not null)";
118 | if ([_attachModel isEqualToString:@"Spawn"]) {
119 | textField.text = canonicalExecutablePath;
120 | }else {
121 | textField.text = [canonicalExecutablePath lastPathComponent];
122 | }
123 |
124 | textField.enabled = NO;
125 | textField.textColor = [UIColor lightGrayColor];
126 | }];
127 |
128 | UIAlertAction *okaction = [UIAlertAction actionWithTitle:@"▶ Start Server" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
129 | NSMutableArray *args = [NSMutableArray array];
130 |
131 | UITextField *tf_server = panel.textFields[0];
132 |
133 | UITextField *tf_ip = nil;
134 | UITextField *tf_a = nil;
135 | if ([_attachModel isEqualToString:@"Attach"]) {
136 | tf_ip = panel.textFields[1];
137 | tf_a = panel.textFields[2];
138 | }else {
139 | tf_ip = panel.textFields[2];
140 | tf_a = panel.textFields[1];
141 | }
142 |
143 | UITextField *tf_exepath = panel.textFields[3];
144 |
145 | NSString *bin_serverpath = [tf_server.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
146 | if (!bin_serverpath || bin_serverpath.length == 0) {
147 | XLOG(@"server path is null,stop");
148 | return ;
149 | }
150 |
151 | NSString *arg_ipport = [tf_ip.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
152 | if (!arg_ipport || arg_ipport.length == 0) {
153 | XLOG(@"ipport is null,continue");
154 | return ;
155 | }
156 |
157 | if ([_attachModel isEqualToString:@"Attach"]) {
158 | [args addObject:arg_ipport];
159 | [args addObject:@"-a"];
160 | }else {
161 | [args addObject:@"-x"];
162 | [args addObject:@"auto"];
163 | [args addObject:arg_ipport];
164 | }
165 |
166 | NSString *arg_exepath = [tf_exepath.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
167 | [args addObject:arg_exepath];
168 |
169 | XLOG(@"launch path %@",bin_serverpath);
170 | XLOG(@"%@ %@ %@",bin_serverpath,arg_ipport,arg_exepath);
171 | XLOG(@"args: %@",args);
172 |
173 | [[NSUserDefaults standardUserDefaults] setObject:bin_serverpath forKey:@"server_bin_path"] ;
174 | [[NSUserDefaults standardUserDefaults] setObject:arg_ipport forKey:@"ip_port"] ;
175 | [[NSUserDefaults standardUserDefaults] synchronize];
176 |
177 | NSTask * task = [TaskManager sharedManager].runningTask;
178 | if(task){
179 | kill(task.processIdentifier,SIGKILL);
180 | task = nil;
181 | }
182 | task = [[NSTask alloc]init];
183 | [task setLaunchPath:bin_serverpath];
184 | [task setArguments:args];
185 | [task launch];
186 | [TaskManager sharedManager].runningTask = task;
187 | }];
188 | UIAlertAction *cancelaction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
189 | XLOG(@"cancel");
190 | }];
191 |
192 | [panel addAction:okaction];
193 | [panel addAction:cancelaction];
194 | XLOG("vc:%@", vc);
195 | [vc presentViewController:panel animated:YES completion:nil];
196 | }
197 |
198 |
199 | void show_debug_view(UIViewController* showVC, NSString* _bundleid){
200 | UIAlertController *panel = [UIAlertController alertControllerWithTitle:@"Choose Attach Model" message:nil preferredStyle:UIAlertControllerStyleAlert];
201 |
202 | UIAlertAction *attachaction = [UIAlertAction actionWithTitle:@"Attach" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
203 | XLOG(@"Attach Mode");
204 | show_debug_process_view(showVC, _bundleid, @"Attach");
205 | }];
206 | UIAlertAction *spawnaction = [UIAlertAction actionWithTitle:@"Spawn" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
207 | XLOG(@"Spawn Mode");
208 | show_debug_process_view(showVC, _bundleid, @"Spawn");
209 | }];
210 |
211 | UIAlertAction *stopction = [UIAlertAction actionWithTitle:@"🛑Stop" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
212 | XLOG(@"Spawn Mode");
213 | NSTask *task = [TaskManager sharedManager].runningTask;
214 | kill(task.processIdentifier,SIGKILL);
215 | task = nil;
216 | }];
217 |
218 | UIAlertAction *cancelaction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
219 | XLOG(@"cancel");
220 | }];
221 |
222 | [panel addAction:attachaction];
223 | [panel addAction:spawnaction];
224 | [panel addAction:cancelaction];
225 |
226 | NSTask *task = [TaskManager sharedManager].runningTask;
227 | if(task){
228 | [panel addAction:stopction];
229 | }
230 |
231 | [showVC presentViewController:panel animated:YES completion:nil];
232 | }
233 |
234 | %hook SBIconView
235 |
236 | %new
237 | -(void)handleDoubleClick:(UITapGestureRecognizer*)doubleTap
238 | {
239 | NSString* bid = self.icon.application.bundleIdentifier;
240 | XLOG(@"id:%@",bid);
241 | show_debug_view([self findViewController], bid);
242 | }
243 | %end
244 |
245 |
246 | %hook SBIconView
247 |
248 | - (void)didMoveToWindow
249 | {
250 | %orig;
251 | #if TROGGLE_WITH_DOUBLE_TAP
252 | UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleClick:)];
253 | [doubleTap setNumberOfTapsRequired:2];
254 | [self addGestureRecognizer:doubleTap];
255 | NSArray * ges = self.gestureRecognizers;
256 | for(UITapGestureRecognizer * each in ges){
257 | if([each isKindOfClass:[UITapGestureRecognizer class]]){
258 | [each requireGestureRecognizerToFail: doubleTap];
259 | }
260 | }
261 | #endif
262 | }
263 |
264 | - (void)tapGestureDidChange:(id)ges
265 | {
266 | XLOG(@"single click");
267 | %orig;
268 | }
269 |
270 | %end
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
--------------------------------------------------------------------------------
/common.h:
--------------------------------------------------------------------------------
1 | #define TROGGLE_WITH_DOUBLE_TAP 0
2 |
3 | @interface UIView(findvc)
4 | -(UIViewController*)findViewController;
5 | @end
6 |
7 | @implementation UIView(find)
8 | -(UIViewController*)findViewController
9 | {
10 | UIResponder* target= self;
11 | while (target) {
12 | target = target.nextResponder;
13 | if ([target isKindOfClass:[UIViewController class]]) {
14 | break;
15 | }
16 | }
17 | return (UIViewController*)target;
18 | }
19 | @end
20 |
21 | void show_debug_view(UIViewController* showVC, NSString* _bundleid);
--------------------------------------------------------------------------------
/control:
--------------------------------------------------------------------------------
1 | Package: com.harans.tweak.shortcuttodebug
2 | Name: Tap2DebugRootless
3 | Version: 0.1.0
4 | Architecture: iphoneos-arm
5 | Description: 无根越狱下通过 3D Touch 快捷方式打开设置中的“调试”页面
6 | Maintainer: Harlans
7 | Author: Harlans
8 | Section: Tweaks
9 | Depends: mobilesubstrate (>= 0.9.5000)
10 |
--------------------------------------------------------------------------------
/resource/Dopamine2.0.8.ipa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DargonLee/Tap2DebugRootless/9f1cead507f0adc39f5f96ba41891863001e7864/resource/Dopamine2.0.8.ipa
--------------------------------------------------------------------------------
/resource/Filza.ipa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DargonLee/Tap2DebugRootless/9f1cead507f0adc39f5f96ba41891863001e7864/resource/Filza.ipa
--------------------------------------------------------------------------------
/xia0.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | // GCD
5 | #define GCD_RUN_MAIN dispatch_async(dispatch_get_main_queue(),^(){
6 | #define GCD_RUN(__dp_q) dispatch_async(dispatch_queue_create(__dp_q, NULL),^(){
7 | #define GCD_AFTER_MAIN(__dp_af) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(__dp_af * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
8 | #define GCD_AFTER(__dp_af, __dp_q) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(__dp_af * NSEC_PER_SEC)), dispatch_queue_create(__dp_q, NULL), ^{
9 | #define GCD_END });
10 | #define SLEEP(sec) [NSThread sleepForTimeInterval:sec]
11 |
12 | #define XLOG(log, ...) NSLog(@"[tap2debug] " log, ##__VA_ARGS__)
13 |
14 | #define X_OC_NEW_NAME(CLASS_ID, SEL_ID) _x_new_func$##CLASS_ID##$##SEL_ID
15 | #define X_OC_NEW(CLASS_ID, SEL_ID, ...) X_OC_NEW_NAME(CLASS_ID, SEL_ID)(id _id, SEL _sel, ##__VA_ARGS__)
16 |
17 | #define X_OC_ORI_NAME(CLASS_ID, SEL_ID) _x_orig_func$##CLASS_ID##$##SEL_ID
18 | #define X_OC_ORI(CLASS_ID, SEL_ID, ...) (*X_OC_ORI_NAME(CLASS_ID, SEL_ID))(id _id, SEL _sel, ##__VA_ARGS__)
19 |
20 | #define X_OC_HOOK(CLASS_ID, SEL_ID, CLASS_NAME, SEL_NAME) do{ Method _method_$##CLASS_ID##$##SEL_ID = class_getClassMethod(NSClassFromString(@""CLASS_NAME), NSSelectorFromString(@""SEL_NAME)); X_OC_ORI_NAME(CLASS_ID,SEL_ID) = (void*)method_getImplementation(_method_$##CLASS_ID##$##SEL_ID); method_setImplementation(_method_$##CLASS_ID##$##SEL_ID, (IMP)&X_OC_NEW_NAME(CLASS_ID, SEL_ID)); }while(0)
21 |
22 |
23 | #define X_C_NEW_NAME(FUNC_ADDR) _x_c_new_func_##FUNC_ADDR
24 | #define X_C_NEW(FUNC_ADDR, ...) X_C_NEW_NAME(FUNC_ADDR)(##__VA_ARGS__)
25 |
26 | #define X_C_ORI_NAME(FUNC_ADDR) _x_c_orig_func_##FUNC_ADDR
27 | #define X_C_ORI(FUNC_ADDR, ...) (*X_C_ORI_NAME(FUNC_ADDR))(##__VA_ARGS__)
28 |
29 | #define X_C_HOOK(FUNC_ADDR) do{ void* _sub_##FUNC_ADDR = (void*)(_dyld_get_image_vmaddr_slide(0) + FUNC_ADDR); MSHookFunction(_sub_##FUNC_ADDR, X_C_NEW_NAME(FUNC_ADDR), &X_C_ORI_NAME(FUNC_ADDR)); }while(0)
30 |
31 |
--------------------------------------------------------------------------------