一、Ioshook父類方法
1.方法簡介
Ioshook是一個基於Cycript實現的庫,它可以hook Objective-C方法並在運行時對其進行修改、添加與刪除。下面我們會從多個方面進行詳細闡述。
2.方法具體實現
/** * Hook一個對象的類方法 * * @param cls 類對象 * @param selector 方法選擇器 * @param callback 回調函數 * * @return 原始IMP地址 */ + (void *)hookClassMethod:(Class)cls selector:(SEL)selector callback:(void *)callback; /** * Hook一個對象的實例方法 * * @param cls 類對象 * @param selector 方法選擇器 * @param callback 回調函數 * * @return 原始IMP地址 */ + (void *)hookInstanceMethod:(Class)cls selector:(SEL)selector callback:(void *)callback;
3.方法使用示例
以Hook UIAlertView 的 show 方法為例,我們可以實現自定義 UIAlertView 顯示時的行為。
Class cls = objc_getClass("UIAlertView");
SEL sel = @selector(show);
[Ioshook hookInstanceMethod:cls selector:sel callback:&showCallback];
// 實現 showCallback 方法
void showCallback(id self, SEL sel) {
NSLog(@"custom show action");
}
二、子類重寫
1.重寫方法實現
除了通過 hook 來修改方法的行為,我們還可以通過 subclass 的方法來重寫方法的實現,以此實現目標。
@interface TargetClass : NSObject
- (void)originalMethod;
@end
@implementation TargetClass
- (void)originalMethod {
NSLog(@"original method");
}
@end
@interface SubClass : TargetClass@end
@implementation SubClass
- (void)originalMethod {
NSLog(@"new method");
}
@end
2.重寫方法使用示例
以 Hook UIViewController 的 viewDidAppear: 方法為例,我們可以在所有繼承於 UIViewController 的子類中增加上報事件:
@implementation UIViewController (CustomEvent)
+ (void)load {
// Only add once
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// subclass
[self mk_customHookMethod:@selector(viewDidAppear:) tarClass:self.newClass usingBlock:^(MKAspectInfo *info) {
UIViewController *controller = (UIViewController *)info.instance;
NSLog(@"custom event report: %@", NSStringFromClass([controller class]));
}];
});
}
@end
@interface UIViewController (CustomEvent) @end
@implementation UIViewController (CustomEvent)
// Override this method to return subclass
+ (Class)newClass {
// Allocate a new class,subclass of the original
NSString *className = NSStringFromClass(self);
Class newClass = objc_allocateClassPair(self, [className stringByAppendingString:@"_CustomEvent"].UTF8String, 0);
// Update hook for subclasses
[newClass aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionAfter usingBlock:^(id info) {
UIViewController *controller = (UIViewController *)info.instance;
NSLog(@"custom event report: %@", NSStringFromClass([controller class]));
} error:nil];
objc_registerClassPair(newClass);
return newClass;
}
@end
三、使用場景
1.日誌列印
在開發和調試過程中,日誌列印是件非常重要的事情。我們可以通過 hook 的形式實現全局的日誌列印。下面以 YYLog 框架為例:
void _objc_msgForward(void) {
// Hook it
orig_objc_msgForward();
// Do something with it
NSLog(@"classname : %@ SEL: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
2.檢查錯誤
在發布的應用中,一個小小的錯誤有可能導致崩潰。通過 hook 可以實現全局的錯誤檢測和上報。
// Define a new method
- (void)xxx_NSLog:(NSString *)format, ... {
va_list argp;
va_start(argp, format);
NSString *str = [[NSString alloc] initWithFormat:format arguments:argp];
va_end(argp);
// Do something with the log
NSLog(@"%@", str);
// Call the old method
[self xxx_NSLog:format,...];
}
// Hook NSUncaughtExceptionHandler
if (getenv("DEBUG_MODE")) { // debug mode
NSSetUncaughtExceptionHandler(&CBLDebugHandleException);
} else { // release mode
NSSetUncaughtExceptionHandler(&CBLReleaseHandleException);
}
// Implement CBLDebugHandleException and CBLReleaseHandleException functions to handle errors
3.統計調用次數
很多應用都需要進行功能點調用次數的統計。通過 hook 可以實現全局的統計,提高開發效率。
@implementation UIView (Count)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self aspect_hookSelector:@selector(didMoveToSuperview) withOptions:AspectPositionAfter usingBlock:^() {
// Statistics code here
} error:nil];
});
}
@end
4.網路監測
通過 hook 可以實現網路請求的監測,從而實現全局的網路監測。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = objc_getClass("__NSCFURLSessionTask");
[Ioshook hookInstanceMethod:cls selector:@selector(cancel) callback:(void *)&HookedNSURLSessionTaskCancel];
});
}
void HookedNSURLSessionTaskCancel(NSURLSessionTask *self, SEL _cmd) {
// Statistics network interrupt times
[self HookedNSURLSessionTaskCancel];
}
四、小結
使用 hook 的方式,可以實現很多應用所需要的功能,例如日誌列印、錯誤檢測、調用次數統計、網路監測等等。對了解 iOS 運行機制和 Objective-C 方法有較深入的理解有一定幫助。以上是一些功能點的例子,我們也可以根據實際需要進行策略和實現。希望對大家有所幫助。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/241439.html
微信掃一掃
支付寶掃一掃