需求是,旧项目建议,需要使用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的相关处理方法了。
}
钻研工具人测试不易,赞我!