美文网首页
关于webview注入js时机的问题

关于webview注入js时机的问题

作者: child_cool | 来源:发表于2018-10-17 18:03 被阅读170次

最直接的解决办法
webview加载会先去查看该方法是否实现
NSObject添加一个扩展去实现webView:didCreateJavaScriptContext:forFrame:方法

  • 问题
    该方法属于苹果的私有方法,直接实现,有很大概率被苹果据掉

对上面的解决方法优化思路

该方案来源于对听云sdk的反编译代码分析

方案一
  • 听云的sdk启动位置为main函数,
  • 根据app的启动原理分析,mach-o加载结束加载sdk,runtime给NSObject添加webView:didCreateJavaScriptContext:forFrame:方法实现,此时注入js
  • 如果需要上架,必须将 webView:didCreateJavaScriptContext:forFrame: 加密之后,反解密放入,直接显示该方法被拒可能性很大
  • 这里只是表达主要思路和解决方案
#import "JSInjection.h"
#import <objc/runtime.h>
#import <JavaScriptCore/JavaScriptCore.h>

@implementation JSInjection

+ (void)start {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        //JSContext
        Method imageNamedMethod = class_getClassMethod([NSObject class], @selector(webView:didCreateJavaScriptContext:forFrame:));
        
        if (imageNamedMethod == nil) {
            
            class_addMethod([NSObject class], @selector(webView:didCreateJavaScriptContext:forFrame:), class_getMethodImplementation([self class], @selector(test_webView:didCreateJavaScriptContext:forFrame:)),method_getTypeEncoding(imageNamedMethod));
        }
    });
}

- (void)test_webView:(id)unuse didCreateJavaScriptContext:(JSContext *)ctx forFrame:(id)frame
{
    NSLog(@"js注入位置");
}

@end

调用位置

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "JSInjection.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        [JSInjection start];
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
方案二
  • 本方案基于上面的解决思路,如果不想写代码在main函数中,可以选择nsobject的分类+load方法中,和上面的代码基本类似
  • 问题:听云没有采用这种方式的原因应该是sdk无法对该方法完全控制,如果直接在项目中使用,不需要sdk可以采用这种方式

相关文章

网友评论

      本文标题:关于webview注入js时机的问题

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