[iOS]WKWebView的使用

demo:https://download.csdn.net/download/u012881779/10928927
使用WKWebView加载H5,并与之进行一些交互。
[GABaseWKWebView]

#import "GABaseWKWebView.h"

@implementation GABaseWKWebView

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame configuration:(nonnull WKWebViewConfiguration *)configuration {
    self = [super initWithFrame:frame configuration:configuration];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (void)setUserAgentInfo {
    // userAgent设置
    [self evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
        NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
        NSString *appVer = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
        NSString *oldAgent = result;
        NSString *newAgent;
        // 给User-Agent添加额外的信息 - 区分来自哪个app
        if ([oldAgent containsString:@"appmark"]) {
            newAgent = oldAgent;
        } else {
            newAgent = [NSString stringWithFormat:@"%@;AppInfo:appName=%@&&appVer=%@", oldAgent, @"appmark", appVer];
        }
        // 设置global User-Agent
        if (@available(iOS 9.0, *)) {
            [self setCustomUserAgent:newAgent];
        }
    }];
}

@end

[GABaseWKWebViewController]

#import "GABaseWKWebViewController.h"
#import <WebKit/WebKit.h>
#import "GABaseWKWebView.h"

@interface GABaseWKWebViewController () <WKNavigationDelegate, WKScriptMessageHandler>

@property (strong, nonatomic) GABaseWKWebView *webView;
@property (strong, nonatomic) NSArray *nameMArr;
@property (nonatomic, strong) NSString *loadUrl;

@end

@implementation GABaseWKWebViewController

- (void)dealloc {
    _loadUrl = nil;
    _webView = nil;
    _nameMArr = nil;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if (!_webView) {
        _webView = [[GABaseWKWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
        _webView.navigationDelegate = self;
    }
    [self.view addSubview:_webView];
    
    /*
     链接不支持https协议时,需要去Info.plist设置允许任意加载
     App Transport Security Settings
        Allow Arbitrary Loads           YES
     */
    NSURL *pathUrl = [self handleLoadUrl:_loadUrl];
    [_webView loadRequest:[NSURLRequest requestWithURL:pathUrl]];
}

- (NSURL *)handleLoadUrl:(NSString *)urlString {
    // 处理url带有中文的
    NSString *encodedString = (NSString*) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)urlString,(CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]",NULL, kCFStringEncodingUTF8));
    NSURL *url = [NSURL URLWithString:encodedString];
    return url;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self addScriptAction];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self removeScriptAction];
}

// 注入JavaScript与原生交互协议
// JS 端可通过 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 发送消息
- (void)addScriptAction {
    if (!_nameMArr) {
        _nameMArr = [[NSArray alloc] initWithObjects:@"goHomeIos",@"sharePagesIos",@"getUserInfoIos",nil];
    }
    for (NSString *subName in _nameMArr) {
        [_webView.configuration.userContentController addScriptMessageHandler:self name:subName];
    }
}

// 移除注入的协议
- (void)removeScriptAction {
    if (_nameMArr) {
        for (NSString *subName in _nameMArr) {
            [_webView.configuration.userContentController removeScriptMessageHandlerForName:subName];
        }
    }
}

#pragma mark - WKNavigationDelegate

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"开始加载");
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"内容开始返回");
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"加载完成");
}

- (void)webView:(WKWebView *)webView didFailLoadWithError:(nonnull NSError *)error {
    NSLog(@"加载失败 error : %@",error.description);
}

// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (navigationAction.targetFrame == nil) {
        [webView loadRequest:navigationAction.request];
    }
    NSURL *URL = navigationAction.request.URL;
    NSString *urlPath = [URL absoluteString];
    NSString *scheme = [URL scheme];
    NSString *resourceSpecifier = [URL resourceSpecifier];
    
    if ([scheme isEqualToString:@"tel"]) {
        NSString *callPhone = [NSString stringWithFormat:@"telprompt://%@", resourceSpecifier];
        // 防止iOS 10及其之后,拨打电话系统弹出框延迟出现
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone]];
        });
        decisionHandler(WKNavigationActionPolicyCancel);
    } else if ([scheme isEqualToString:@"mqq"]) {
        if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"mqq://"]]) {
            NSString *callQQ = [NSString stringWithFormat:@"mqq://%@", resourceSpecifier];
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callQQ]];
            });
        }
        decisionHandler(WKNavigationActionPolicyCancel);
    } else if ([scheme isEqualToString:@"mailto"]) {
        NSString *callEmail = [NSString stringWithFormat:@"mailto://%@", resourceSpecifier];
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callEmail]];
        });
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    decisionHandler(WKNavigationResponsePolicyAllow);
}

#pragma mark - 执行JavaScript代码

- (void)loadJs:(NSString *)js {
    // ios11要求evaluateJavaScript主线程
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"evaluateJavaScript error = %@\n", error);
            }
        }];
    });
}

#pragma mark - WKScriptMessageHandler
/*
 在协议方法中获取JavaScript端传递的事件和参数
 WKScriptMessage
    name    协议名称
    body    传递的参数
 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"body:%@", message.body);
    NSLog(@"message.name = %@",message.name);
    NSString *name = message.name;
    if ([name isEqualToString:@"goHomeIos"]) {
        // 首页
    } else if ([name isEqualToString:@"sharePagesIos"]) {
        // 分享
    } else if ([message.name isEqualToString:@"getUserInfoIos"]) {
        // 获取用户信息
        [self getUsrInfo];
    }
}

- (void)getUsrInfo {
    NSString *usrId = @"UserID";
    NSString *token = @"Token";
    NSString *identity = @"Identity";
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:token,@"token", identity,@"identity", usrId,@"userId", nil];
    NSString *jsBody = [self dictionaryToJson:dic];
    NSString *js = [NSString stringWithFormat:@"javascript:vueObj.getUserInfoPage('%@')", jsBody];
    [self loadJs:js];
}

- (NSString *)dictionaryToJson:(NSDictionary *)dic {
    if (dic == nil) {
        return @"";
    }
    NSError *parseError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@" " withString:@""];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
    return jsonStr;
}

@end

app与html交互,html端操作

#pragma mark - WKScriptMessageHandler
/*
 在协议方法中获取JavaScript端传递的事件和参数
 WKScriptMessage
 name    协议名称
 body    传递的参数
 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"body:%@", message.body);
    NSLog(@"message.name = %@",message.name);
    NSString *name = message.name;
    if ([name isEqualToString:@"goBack"]) {
        // 返回
        [self.navigationController popViewControllerAnimated:YES];
    } else if ([name isEqualToString:@"addContent"]) {
        // 添加
        NSString *js = @"addDiv(10)";
        [self loadJs:js];
    } else if ([message.name isEqualToString:@"userInfo"]) {
        // 信息
        NSString *usrId = @"UserID";
        NSString *token = @"Token";
        NSString *identity = @"Identity";
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:token,@"token", identity,@"identity", usrId,@"userId", nil];
        NSString *jsBody = [self dictionaryToJson:dic];
        NSString *js = [NSString stringWithFormat:@"dealInfo('%@')", jsBody];
        [self loadJs:js];
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
    <link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
    <button id ="returnId">返回</button>
    <button id="addId">添加</button>
    <button id="userInfoId">用户信息</button>
    <div id = "did">这是一个div</div>
    <p id = "pid">hello</p>
    <script src="script.js"></script>
</body>
</html>
// 添加div
function addDiv (num) {
    var count = num;
    var pElement = document.getElementById("pid");
    for (var i = 0 ; i < count ; i ++) {
        var div = document.createElement("div");
        div.className = "divname";
        div.innerText = i+"div";
        div.style.color = "#ff0000";
        pElement.append(div);
    }
}

// 返回
var returnBut = document.getElementById("returnId");
returnBut.addEventListener("click",returnAction);
function returnAction() {
    window.webkit.messageHandlers.goBack.postMessage({"title":"标题1","content":"内容1"})
}

// 添加div
var addBut = document.getElementById("addId");
addBut.addEventListener("click",addAction);
function addAction () {
    window.webkit.messageHandlers.addContent.postMessage({"title":"标题2","content":"内容2"})
}

// 信息
var userInfoBut = document.getElementById("userInfoId");
userInfoBut.addEventListener("click",userInfoAction);
function userInfoAction () {
    window.webkit.messageHandlers.userInfo.postMessage({"title":"标题3","content":"内容3"})
}

// 处理信息
function dealInfo (info) {
    var pElement = document.getElementById("pid");
    pElement.innerText = info;
}



TO:
[iOS]WKWebView的使用--API篇
iOS11.3 WKWebView清除cookie所踩的坑!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值