美文网首页
hook delegate 正确姿势

hook delegate 正确姿势

作者: 钟环 | 来源:发表于2019-11-23 16:30 被阅读0次

    核心hook方法:网上有类似hook方式,但没考虑继承和子类的问题,会导致循环调用crash。

    NSDictionary * checkIfObject(Class object,SEL selector) {
        Class objSuperClass = [object superclass];
        while (objSuperClass != Nil) {
            BOOL isMethodOverridden = [object methodForSelector: selector] != [objSuperClass instanceMethodForSelector: selector];
            if (isMethodOverridden) {
                return @{@"class":objSuperClass,@"exist":@(YES)};
            }
            objSuperClass = [objSuperClass superclass];
        }
        return @{@"class":object,@"exist":@(NO)};
    }
    
    void exchangeMethod(Class oriClass, SEL originalSel, Class replacedClass, SEL replacedSel, SEL orginReplaceSel) {
        NSDictionary *dict = checkIfObject(oriClass, originalSel);
        Class originalClass = dict[@"class"];
        BOOL exist = [dict[@"exist"] boolValue];
        Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
        Method replacedMethod = class_getInstanceMethod(replacedClass, replacedSel);
        if (!exist) {
            Method orginReplaceMethod = class_getInstanceMethod(replacedClass, orginReplaceSel);
            BOOL didAddOriginMethod = class_addMethod(originalClass, originalSel, method_getImplementation(orginReplaceMethod), method_getTypeEncoding(orginReplaceMethod));
            if (didAddOriginMethod) {
                NSLog(@"did Add Origin Replace Method");
            }
            return;
        }
        BOOL didAddMethod = class_addMethod(originalClass, replacedSel, method_getImplementation(replacedMethod), method_getTypeEncoding(replacedMethod));
        if (didAddMethod) {
            Method newMethod = class_getInstanceMethod(originalClass, replacedSel);
            method_exchangeImplementations(originalMethod, newMethod);
        }
    }
    

    使用 案例:(XXXX 前缀)注意实现方式

    - (void)XXXX_setNavigationDelegate:(id<WKNavigationDelegate>)navigationDelegate {
    
        [self XXXX_setNavigationDelegate:navigationDelegate];
    
        exchangeMethod([navigationDelegate class], @selector(webView:decidePolicyForNavigationAction:decisionHandler:), [self class], @selector(XXXX_webView:decidePolicyForNavigationAction:decisionHandler:),@selector(XXXX_oriReplace_webView:decidePolicyForNavigationAction:decisionHandler:));
        
        exchangeMethod([navigationDelegate class], @selector(webView:didStartProvisionalNavigation:), [self class], @selector(XXXX_webView:didStartProvisionalNavigation:),@selector(XXXX_oriReplace_webView:didStartProvisionalNavigation:));
        
        exchangeMethod([navigationDelegate class], @selector(webView:didFinishNavigation:), [self class], @selector(XXXX_webView:didFinishNavigation:),@selector(XXXX_oriReplace_webView:didFinishNavigation:));
        
        exchangeMethod([navigationDelegate class], @selector(webView:didFailProvisionalNavigation:withError:), [self class], @selector(XXXX_webView:didFailProvisionalNavigation:withError:),@selector(XXXX_oriReplace_webView:didFailProvisionalNavigation:withError:));
        
        exchangeMethod([navigationDelegate class], @selector(webView:didFailNavigation:withError:), [self class], @selector(XXXX_webView:didFailNavigation:withError:),@selector(XXXX_oriReplace_webView:didFailNavigation:withError:));
    }
    

    相关文章

      网友评论

          本文标题:hook delegate 正确姿势

          本文链接:https://www.haomeiwen.com/subject/gdmhwctx.html