项目里面很多地方都是用的h5, h5的处理都放在了一个新的控制器里面,里面很多代理方法,在这里记录一下。
很多h5的处理,iOS和js的交互都要通过代理方法去处理。
1、iOS调用js的方法, 例如调用js的跳转方法。
2、iOS获取js的方法,截取方法然后自己去实现。
@protocol WKScriptMessageHandler <NSObject>
@required
/*! @abstract Invoked when a script message is received from a webpage.
@param userContentController The user content controller invoking the
delegate method.
@param message The script message received.
*/
方法中主要是收到JS的回执脚本就会运行一次
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
@end
该代理方法是h5调用js方法的时候,客户端可以获取到并且去做自己的处理。
点击某个按钮,webview加载完成之后原生可以获取到里面的某些需要的数据去设置。
h5调原生本地函数
/**
当从网页收到脚本消息时调用。
@param userContentController 调用委托方法的用户内容控制器。
@param message 收到的脚本消息。
*/
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
NSDictionary *bodyParam = (NSDictionary*)message.body;
NSString *func = [bodyParam objectForKey:@"function"];
NSLog(@"MessageHandler Name:%@", message.name);
NSLog(@"MessageHandler Body:%@", message.body);
NSLog(@"MessageHandler Function:%@",func);
//本人喜欢只定义一个MessageHandler协议 当然可以定义其他MessageHandler协议
if ([message.name isEqualToString:@"Native"])
{
NSDictionary *parameters = [bodyParam objectForKey:@"parameters"];
//调用本地函数
if([func isEqualToString:@"modifySuccess"])
{
NSLog(@"在这里面去做弹窗提示,为视图设置数据,调用原生的返回等操作");
}
else if([func isEqualToString:@"callNativeHomePageBack"])
{
NSLog(@"在这里面去做弹窗提示,为视图设置数据,调用原生的返回等操作");
}
else if ([func isEqualToString:@"callNativeWebShare"]){
NSLog(@"调用原生的分享功能");
}
else if ([func isEqualToString:@"callNativeWebLoginView"]){
NSLog(@"跳转到登录页面");
}
else if ([func isEqualToString:@"callNativeWebPageShare"]){
NSLog(@"弹出本地的分享菜单");
}
else if ([func isEqualToString:@"callNativeProduct"]){
NSLog(@"点击立即购买按钮,去购买操作");
}
else if ([func isEqualToString:@"keyboardBarShow"]){
NSLog(@"web要求评论条出现");
}
else if ([func isEqualToString:@"keyboardBarHide"]){
NSLog(@"web要求评论条消失");
}
else if ([func isEqualToString:@"callNativeWebviewWithURL"]){
NSLog(@"跳出新浏览器,创建一个webview去显示新页面");
}
else if ([func isEqualToString:@"callNativeWebviewWithURLWithNaviBar"]){
NSLog(@"跳出新浏览器");
}
else if ([func isEqualToString:@"keyboardBarShowUpdateCommentCount"]){
NSLog(@"刷新评论的数据");
}
}
}
这个是检测收到html的js消息的时候, 我们客户端做的操作。
上面的就是收到html的修改用户信息、分享、点击客服、收藏等消息。
原生调用js方法
例:
文章详情页面发表评论功能,发评论的内容是客户端控制的,客户端才拥有。
点击发送按钮,需要调用js方法,告诉h5发表评论的内容。
点击发送按钮需要调用h5的js方法:
NSString *contentString = [<#评论的内容#> stringByReplacingOccurrencesOfString:@"\n" withString:@"<br/>"];
[wkWebView evaluateJavaScript:[NSString stringWithFormat:@"keyboardBarCommentReturn('%@')",contentString] completionHandler:^(id _Nullable response, NSError * _Nullable error){
}];
例二:
点击底部的评论按钮,详情页滚动到评论,需要h5去做,原生告诉h5
[wkWebView evaluateJavaScript:[NSString stringWithFormat:@"keyboardBarRecordReturn('1')"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
}];
代理方法
WKUIDelegate
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
NSLog(@"%s", __FUNCTION__);
[self.wkWebview loadRequest:[self fixRequest:navigationAction.request]];
return webView;
}
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"%s", __FUNCTION__);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];
[self presentViewController:alert animated:YES completion:NULL];
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
NSLog(@"%s", __FUNCTION__);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"confirm" message:@"JS调用confirm" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler(YES);
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler(NO);
}]];
[self presentViewController:alert animated:YES completion:NULL];
NSLog(@"%@", message);
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
NSLog(@"%s", __FUNCTION__);
NSLog(@"%@", prompt);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"textinput" message:@"JS调用输入框" preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.textColor = [UIColor redColor];
}];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler([[alert.textFields lastObject] text]);
}]];
[self presentViewController:alert animated:YES completion:NULL];
}
上面的那个是WKUIDelegate, 可以检测到js到弹窗, 然后我们出来我们自己的样式。弹出什么和做什么操作。
WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSLog(@"%s", __FUNCTION__);
NSURLRequest *originalRequest = navigationAction.request;
[self fixRequest:originalRequest];
[webView evaluateJavaScript:[self jsString:navigationAction.request.URL.absoluteString] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (error == nil) {
NSLog(@"成功注入");
}
}];
decisionHandler(WKNavigationActionPolicyAllow);
}
//可以在该代理方法中 获取头部信息 包括过期日期 修改日期等
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"%s", __FUNCTION__);
NSString *cacheControl = [(NSHTTPURLResponse*)navigationResponse.response allHeaderFields][@"Cache-Control"]; // max-age, must-revalidate, no-cache
NSArray *cacheControlEntities = [cacheControl componentsSeparatedByString:@","];
for(NSString *substring in cacheControlEntities) {
if([substring rangeOfString:@"max-age"].location != NSNotFound) {
// do some processing to calculate expiresOn
NSString *maxAge = nil;
NSArray *array = [substring componentsSeparatedByString:@"="];
if([array count] > 1)
maxAge = array[1];
NSDate * expiresOnDate = [[NSDate date] dateByAddingTimeInterval:[maxAge intValue]];
//保存过期时间
[[NSUserDefaults standardUserDefaults] setObject:expiresOnDate forKey:kHtml_gqsj];
}
}
decisionHandler(WKNavigationResponsePolicyAllow);
}
//请求开始的代理方法
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
}
//请求结束的代理方法。
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
NSLog(@"%s", __FUNCTION__);
}
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"%s", __FUNCTION__);
}
网友评论