TimerFix 快速編輯鬧鐘
前言
有個最近才從 Android 跳槽的同學向我抱怨 iOS 內建的鬧鐘,其編輯過程繁瑣不直觀。
她表示 Android 直接點選欲編輯的鬧鐘即可編輯,iOS 則需要多一步點擊左上角編輯
的步驟。
的確如她所言,點擊左上角編輯
後,進入的編輯狀態著實雞肋,除了刪除、編輯項目外無其他功能。
直接將項目往左拖曳也能達到刪除項目的功能,且比點擊編輯
→-
→刪除
還要來得快捷。
於是,我撰寫了擴充套件 TimerFix,來實現快速編輯鬧鐘。
實作過程
-
使用 Reveal 檢視
編輯
按鈕,發現是個 UINavigationButton(UIButton 類別)。 -
使用 LLDB 指令
po [UIButton allTargets]
,來取得 target 與 action:po [0x10328af30 allTargets] {( <UIBarButtonItem: 0x10326e1e0> target=0x10323c080 action=_toggleEditing: title='編輯' )}
-
使用 LLDB 指令
po target
,來取得 Controller:po 0x10323c080 <MTAAlarmTableViewController: 0x10323c080>
-
透過查閱
.h
檔,尋找 action 方法_toggleEditing:
實現的地方:- MTAAlarmTableViewController 中沒有實現
_toggleEditing:
,往父類找。 - MTAAlarmTableViewController 繼承於 MTATableViewController。
- MTATableViewController 繼承於 UITableViewController。
- UITableViewController 繼承於 UIViewController。
- 最終發現於 UIViewController 中實現了
_toggleEditing:
。
- MTAAlarmTableViewController 中沒有實現
-
使用 IDA 逆向 UIKitCore 找到 UIViewController 中的
_toggleEditing:
偽代碼:void __cdecl -[UIViewController _toggleEditing:](UIViewController *self, SEL a2, id a3) { char v3; // al v3 = (unsigned __int64)-[UIViewController isEditing](self, "isEditing", a3); -[UIViewController setEditing:animated:](self, "setEditing:animated:", (unsigned __int8)(v3 ^ 1), 1LL); }
可見是呼叫了
[UIViewController setEditing:animated:]
才進入編輯狀態。 -
接著,撰寫程式碼,使不是處於編輯狀態的項目也能點選:
%hook MTAAlarmTableViewController -(void)viewDidLoad { %orig; [self.tableView setAllowsSelection:YES]; } %end
實測後發現點選後還是沒反應。
-
使用 IDA 逆向處理項目點選的方法,發現當中存在是否處於編輯狀態的判斷。
再結合上述 UIKitCore 的逆向,在
%orig;
前先[self setEditing:YES animated:NO];
即可:%hook MTAAlarmTableViewController -(void)tableView:(id)arg1 didSelectRowAtIndexPath:(id)arg2 { if(![self isEditing]) { is_tap_cell = YES; [self setEditing:YES animated:NO]; } %orig; } %end
-
最後再於 MTAAlarmTableViewCell 做一些外觀上的修飾:
static BOOL is_tap_cell = NO; %hook MTAAlarmTableViewCell -(void)setEditing:(_Bool)arg1 animated:(_Bool)arg2 { if(is_tap_cell) { %orig(NO,NO); } else { %orig; } } -(void)refreshUI:(id)arg1 animated:(_Bool)arg2 { is_tap_cell = NO; %orig; } %end
完成。
貼文底端