reference resources:IOS native and JS interaction、 Reference demo address
Tips: it is necessary to learn some web technology
Uiwebview has been abandoned by Apple’s father. Let’s just say that wkwebview actually has similar methods and ideas
Demo address
Basic use
Load web page
- Import
#import <WebKit/WebKit.h>
- Lazy loading
@property(nonatomic,strong)WKWebView *webView;
- (WKWebView *)webView
{
if (!_webView) {
WKWebView *view = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:view];
_webView = view;
}
return _webView;
}
- Load local, network
//Network
NSString *url = @"https://www.baidu.com";
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
//Local
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"index" ofType:@"html"];
NSURL *baseUrl = [[NSBundle mainBundle]bundleURL];
NSString *sourceString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
[self.webView loadHTMLString:sourceString baseURL:baseUrl];
Swift version:
lazy var webView: WKWebView = {
var webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height))
self.view.addSubview(webView)
return webView
}()
let url = "https://www.baidu.com"
webView.load(URLRequest.init(url: URL.init(string: url)!))


agent
Compliance agentnavigationDelegateIt mainly handles some jump and load operations
Compliance agentUIDelegate, mainly dealing with JS script, confirmation box, warning box, etc
navigationDelegate
Handle jumps, loads, etc
There are also many agency methods. Let’s talk about a few
- Authentication is basically not used
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
The company wants to connect to a third-party platform, and then has a wonderful logic. After the user fills in the relevant information, click Submit, and then the server returns the source code of a web page... The web page needs to be loaded with WebView. When implementing, I found that the simple web page source code I wrote can be loaded, but what the server returns is that it cannot be loaded. Later, after saving the source code as a file, I opened it with a browser and found that the site linked to the web page is an untrusted site. It should be untrusted because the server certificate is invalid.
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
NSLog(@"didReceiveAuthenticationChallenge");
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,card);
}
}
-
decidePolicyForNavigationAction、decidePolicyForNavigationResponse
Whether to jump before the request and whether to jump after the request response (the method will be called many times because there is jump)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler API_AVAILABLE(macos(10.15), ios(13.0));
Either of the two methods
typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {
WKNavigationActionPolicyCancel,
WKNavigationActionPolicyAllow,
} API_AVAILABLE(macos(10.10), ios(8.0));
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSLog(@"decidePolicyForNavigationAction");
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
NSLog(@"decidePolicyForNavigationResponse");
decisionHandler(WKNavigationResponsePolicyAllow);
}
Wknavigationactionpolicyallow: Web pages can jump normally
Wknavigationactionpolicycancel: cancel page Jump
This method can be used to intercept URL interaction with the web
Get protocol, domain name, full path, relative path, port, path, search, parameter
example:
NSLog(@"scheme:%@",navigationAction.request.URL.scheme);
NSLog(@"host:%@",navigationAction.request.URL.host);
NSLog(@"absoluteString:%@",navigationAction.request.URL.absoluteString);
NSLog(@"relativePath:%@",navigationAction.request.URL.relativePath);
NSLog(@"port:%@",navigationAction.request.URL.port);
NSLog(@"path:%@",navigationAction.request.URL.path);
NSLog(@"pathComponents:%@",navigationAction.request.URL.pathComponents);
NSLog(@"query:%@",navigationAction.request.URL.query);
NSLog(@"decidePolicyForNavigationAction");
------ ViewController. M ------ line 65 ------ scheme: HTTPS
------ ViewController. M ------ line 66 ------ host: hqhhtest hqhh520. cn
------ ViewController. M ------ line 67 ------ absolutestring: https://hqhhtest.hqhh520.cn/h5/#/carRental?classId=9
------ ViewController. M ------ line 68 ------ relativepath: / H5
------ ViewController. M ------ line 69 ------ port: (null)
------ ViewController. M ------ line 70 ------ path: / H5
------ ViewController. M ------ line 71 ------ pathcomponents:(
"/",
h5
)
------ ViewController. M ------ line 72 ------ query: (null)
If the local interface is loaded, the action and response methods will not be called actively
- The page starts loading、Content return. loading completed、Loading failed*
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
NSLog(@"didStartProvisionalNavigation");
}
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
NSLog(@"didCommitNavigation");
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
NSLog(@"didFinishNavigation");
}
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"didFailNavigation");
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
//If the response is not allowed after the response, the load will fail
NSLog(@"didFailProvisionalNavigation");
}
UIDelegate
Handle JS script, confirmation box, warning box, etc
JS add pop-up box code Oh
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
Uialertcontroller * alert = [uialertcontroller alertcontrollerwithtitle: @ "reminder" message: message preferredstyle: uialertcontrollerstylealert];
[alert Addaction: [uialertaction actionwithtitle: @ "got it" style: uialertactionstylecancel handler: ^ (uialertaction * _nonullaction){
completionHandler();
}]];
[self presentViewController:alert animated:YES completion:nil];
}
Small function
Return and advance to the previous interface
if (self.webView.canGoBack) {
[self.webView goBack];
}
if (self.webView.canGoForward) {
[self.webView goForward];
}
Get title, get loading progress
Remember to destroy dealloc and remove listening
[_webView removeObserver:self forKeyPath:@"title"];
[_webView removeObserver:self forKeyPath:@"estimatedProgress"];
[_webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
- (void)addObserver
{
[self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
[self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
NSLog(@"keyPath:%@",keyPath);
if ([keyPath isEqualToString:@"title"]) {
self.title = self.webView.title;
} else if ([keyPath isEqualToString:@"estimatedProgress"]) {
NSLog(@"%f",self.webView.estimatedProgress);
} else if ([keyPath isEqualToString:@"contentSize"]) {
NSLog(@"%@",object);
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
interactive
url redirection
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSLog(@"URL:%@",navigationAction.request.URL);
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
NSLog(@"decidePolicyForNavigationResponse");
decisionHandler(WKNavigationResponsePolicyAllow);
}
Determine URL
Messagehandler (native)
Extension points: configuration, usercontentcontroller
Initialization settings
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
//Set preferences
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
//The default value is 0. In fact, it is not recommended to set it here
config.preferences.minimumFontSize = 10;
//Is JavaScript supported
config.preferences.javaScriptEnabled = YES;
//Can I open a window without user interaction
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
Click JS native response
To test:Prepare the HTML file locally, the JS method and the three parties here
The writing method of WebView JavaScript bridge is slightly different
To test:Prepare the HTML file locally. The JS method here is slightly different from the writing method of the three-party WebView JavaScript bridge
To test:Prepare the HTML file locally. The JS method here is slightly different from the writing method of the three-party WebView JavaScript bridge
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

Setting up usercontentcontroller compliance agentWKScriptMessageHandler
Implementation method
WKUserContentController *userContentController = config.userContentController;
[userContentController addScriptMessageHandler:self name:@"showMobile"];
[userContentController addScriptMessageHandler:self name:@"showName"];
[userContentController addScriptMessageHandler:self name:@"showSendMsg"];
remove
WKUserContentController *controller = self.webView.configuration.userContentController;
[controller removeScriptMessageHandlerForName:@"showMobile"];
[controller removeScriptMessageHandlerForName:@"showName"];
[controller removeScriptMessageHandlerForName:@"showSendMsg"];
agent
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
NSLog(@"%@",message.body);
NSLog(@"%@",message.name);
}
Native driven JS response evaluatejavascript
You can write several buttons to trigger
JS code

[self.webView evaluateJavaScript:@"alertMobile()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//JS return result
NSLog(@"%@ %@",response,error);
}];
[self.webView evaluateJavaScript:@"alertName('wpp')" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//JS return result
NSLog(@"%@ %@",response,error);
}];
[self. WebView evaluatejavascript: @ "alertsendmsg ('wpp ',' 20 ')" completionhandler: ^ (ID _nullableresponse, nserror * _nullableerror){
//JS return result
NSLog(@"%@ %@",response,error);
}];
Webviewjavascriptbridge (third party)
- Prepare HTML files separately
- The best are the latest libraries, and the old ones may collapse
- Set minimumfontsize to 40, otherwise the interface control is a little small
- The navigationdelegate agent cannot be set separately because the bridge needs to set it
- set a property
#import "WebViewJavascriptBridge.h"
@property(nonatomic,strong)WebViewJavascriptBridge *bridge;
self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[self.bridge setWebViewDelegate:self];
- Set WebView for listening
- (void)addRegisterHandler
{
[self.bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "sweep% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"locationClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "address% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"colorClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "change color% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"shareClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "share% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"payClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "pay% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"shakeClick" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "shake% @", data);
Responsecallback (@ "callback");
}];
[self.bridge registerHandler:@"goback" handler:^(id data, WVJBResponseCallback responseCallback) {
Nslog (@ "return% @", data);
Responsecallback (@ "callback");
}];
}
- JS interaction
[self.bridge callhandler: @ "testjsfunction" data: @ "a string" responsecallback: ^ (ID responsedata){
NSLog(@"%@",responseData);
}];
Little tip
Height of budget view
//Avoid constant height callback
@property(nonatomic,assign)CGFloat webViewHeight;
//Callback height
@property(nonatomic,copy)void (^refreshUIBlock)(void);
if ([keyPath isEqualToString:@"contentSize"]) {
if (self.webViewHeight == self.webView.scrollView.contentSize.height) {
return;
}
self.webView.height = self.webView.scrollView.contentSize.height;
self.height = self.webView.height;
self.webViewHeight = self.webView.height;
!self.refreshUIBlock ?: self.refreshUIBlock ();
self.webViewHeight = self.webView.scrollView.contentSize.height;
}
progress bar
Cannot be displayed and added to Scrollview
[self.webView.scrollView addSubview:self.progressView];
@property(nonatomic,strong)UIProgressView *progressView;
- (UIProgressView *)progressView
{
if (!_progressView) {
UIProgressView *view = [[UIProgressView alloc]initWithFrame:CGRectMake(0, 0, self.width, 0)];
[self.webView addSubview:view];
view.progressTintColor = kThemeColor;
//view.trackTintColor = [UIColor lightGrayColor];
_progressView = view;
}
return _progressView;
}
if ([keyPath isEqualToString:@"estimatedProgress"]) {
//NSLog(@"%f",self.webView.estimatedProgress);
[self.progressView setProgress:self.webView.estimatedProgress animated:YES];
self.progressView.hidden = self.webView.estimatedProgress == 1.0 ? YES : NO;
}