美文网首页mPaaS
mPaaS H5容器注入自定义bridge

mPaaS H5容器注入自定义bridge

作者: 山已几孑 | 来源:发表于2021-04-01 15:37 被阅读0次

    需求是,旧项目建议,需要使用h5容器,且支持旧页面的桥接JS

    原有webViewController中,注入js的姿势是在初始化WKWebView中,通过WKWebViewConfiguration中实现的,如下

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    //不通过用户交互,是否可以打开窗口
    config.preferences.javaScriptCanOpenWindowsAutomatically = true;
    //是否支持JavaScript
    config.preferences.javaScriptEnabled = true;
    //是否支持访问本地html
    [config.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
    
    WKUserContentController * _userController = [[event valueForKey:@"wkConfiguration"] userContentController];
    NSString *path = [NSBundle.mainBundle pathForResource:@"callNative" ofType:@"js"];
    if (path) {
          NSString *jsSource = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
          WKUserScript *script = [[WKUserScript alloc] initWithSource:jsSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
          [_userController addUserScript:script];
    }
    config.userContentController = _userController;
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:self.config];
    
    

    重点是mPaaS怎么注入

    PS: 纯个人摸索,都是野路子,如果大家能找到mPaaS的支持,让他们支招最好了。

    mPaaS的H5容器,结构和初始化都是个迷,开始找到了PSDViewControllerProtocol,看这些方法名,再看这注释,完美,结果都试了一遍,没一个靠谱的。

    @protocol PSDViewControllerProtocol <NSObject>
    - (NSArray *)dynamicJsUrls; // 动态注入js数组
    - (NSString *)startupParamsJs; // 启动参数js
    - (NSString *)codeSnippets4InsertAlipayJsBridgeFile; // 动态插入js片段;该方法是在插入js之前修改js文件
    - (void)startFirstLoadRequest:(NSURL *)url; // 如果实现了该方法,需要自己loadRequest;该方法是第一次进入页面发起的请求
    - (NSArray *)independenceUserScripts; // PSDWebViewUserScript
    - (NSArray *)relayOnAlipayJsBridgeUserScripts; // PSDWebViewUserScript
    - (void)injectIndependenceJs; // 注入单独的JS文件
    - (void)injectJsRelyOnAlipayJsBridge; // 依赖于AlipayJSBridge
    - (NSString *)allJsInjectToJSC; //通过JSC注入的JS
    

    不抱怨了,言归正传

    这里是通过自定义Plugin,监听容器发出的通知,在合适的时机(正在创建,并且最好只执行一次)拿到userController,并修改他的属性。

    自定义Plugin,大家自己去mPaaS文档查吧,不多说,直接上事件的代码

    @interface CustomH5Plugin4Service () <WKScriptMessageHandler>
    @end
    @implementation CustomH5Plugin4Service
    - (void)pluginDidLoad
     {
         self.scope = kPSDScope_Service;
         [self.target addEventListener: kEvent_View_Config withListener:self useCapture:NO];
         [super pluginDidLoad];
    }
    - (void)handleEvent:(PSDEvent *)event
      {
          [super handleEvent:event];
    //      2021-03-22 16:50:00.512681+0800 mmspc[19324:358817] kPSDScope_Service :: scene.create.before
    
          NSLog(@"kPSDScope_Service :: %@", event.eventType);
          /**
    这里是做的测试,当 scene,ready 开始,webView就已经初始化出来了,因此,config相关的内容肯定在前面几个,
    当然后面的也不是没有用处,当你需要获取webView的来修改属性的时候,在后面几个位置才是合理的
    kPSDScope_Service :: session.create
    kPSDScope_Service :: scene.create
    kPSDScope_Session :: scene.load
    kPSDScope_Service :: scene.didload
    kPSDScope_Service :: view.config
    kPSDScope_Service :: view.create
    kPSDScope_Service :: scene.ready WKWebView 有
    kPSDScope_Service :: scene.appear.before WKWebView 有
    kPSDScope_Service :: page.load.domready WKWebView 有
    kPSDScope_Service :: page.load.complete WKWebView 有
    kPSDScope_Service :: navigation.complete WKWebView 有
           */
    
          PSDContext * context = event.context;
          H5WebViewController * webController = context.currentViewController;
          WKWebView * webView = webController.psdContentView;
          
          if ([kEvent_View_Config isEqualToString:event.eventType]) {
              WKUserContentController * _userController = [[event valueForKey:@"wkConfiguration"] userContentController];
              NSString *path = [NSBundle.mainBundle pathForResource:@"callNative" ofType:@"js"];
              if (path) {
                  NSString *jsSource = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
                  WKUserScript *script = [[WKUserScript alloc] initWithSource:jsSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
                  [_userController addUserScript:script];
              }
              [_userController addScriptMessageHandler:self name:@"callNative"];
          }
    }
    
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
        NSLog(@"%s",__func__);
    // 这里就可以写自定义的bridge的相关处理方法了。
    }
    

    钻研工具人测试不易,赞我!

    相关文章

      网友评论

        本文标题:mPaaS H5容器注入自定义bridge

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