由于項(xiàng)目經(jīng)常性會(huì)使用到WKWebView极颓,于是在這里記錄下一下關(guān)于蘋(píng)果WKWebView的要點(diǎn)與遇到的問(wèn)題
基本配置
使用WKWebView之前需要先導(dǎo)入 #import <WebKit/WebKit.h>
//配置WKWebViewConfiguration
注意加上WKScriptMessageHandler
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
//WKUserContentController 主要用于與JS交互
config.userContentController = [[WKUserContentController alloc] init];
[config.userContentController addScriptMessageHandler:self name:@"xxx"];
// 創(chuàng)建WKPreferences
WKPreferences *preference = [[WKPreferences alloc]init];
//最小字體大小 當(dāng)將javaScriptEnabled屬性設(shè)置為NO時(shí),可以看到明顯的效果
preference.minimumFontSize = 0;
//設(shè)置是否支持javaScript 默認(rèn)是支持的
preference.javaScriptEnabled = YES;
// 在iOS上默認(rèn)為NO涝缝,表示是否允許不經(jīng)過(guò)用戶(hù)交互由javaScript自動(dòng)打開(kāi)窗口
preference.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences = preference;
//創(chuàng)建WKWebView
注意寫(xiě)上WKUIDelegate,WKNavigationDelegate
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) configuration:config];
//不顯示滾動(dòng)條
_webView.scrollView.showsVerticalScrollIndicator = NO;
_webView.scrollView.showsHorizontalScrollIndicator = NO;
//設(shè)置代理
_webView.navigationDelegate = self;
_webView.UIDelegate = self;
核心代理方法
webview最主要是使用下面的方法與js進(jìn)行交互
JS端
<script>
let body = {
method1 = "hello world"
}
window.webkit.messageHandlers.xxx.postMessage(body)
</script>
//其中xxx為JS與iOS雙方規(guī)定的相同字符串,body為傳入iOS端的參數(shù)
iOS端
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"xxx"]) {
if [(message.body["method1"] isEqualToString:@"hello world"]) {
//進(jìn)行邏輯處理
}
}
}
關(guān)于webView傳參給JS
WKWebView傳參給JS主要靠evaluateJavaScript方法,由于接觸JS比較少譬重,傳參也著實(shí)費(fèi)了一番功夫才弄明白
1.傳入String類(lèi)型
這個(gè)類(lèi)型是最簡(jiǎn)單的
[webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack('%@')",str] completionHandler:^(id _Nullable object, NSError * _Nullable error) { }
];
2.傳入Array類(lèi)型
[webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack(%@)",array] completionHandler:^(id _Nullable object, NSError * _Nullable error) { }
];
3.傳入Dictionary類(lèi)型
字典類(lèi)型的需要轉(zhuǎn)換為json字符串再傳拒逮,并且去掉空格跟換行符
NSData *data1 = [NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:data1
encoding:NSUTF8StringEncoding];
jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@" " withString:@""];
jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
[webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack('%@')",jsonStr] completionHandler:^(id _Nullable object, NSError * _Nullable error) {
}];
關(guān)于使用Masonry時(shí)webview顯示不完全的問(wèn)題
有時(shí)候webview加載出來(lái)的頁(yè)面會(huì)跟預(yù)期的有偏差,比如位置變了臀规,大小變了滩援,這些時(shí)候只能在loadRequest之前使用Masonry,將webview約束好
[_webView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsZero);
}];
[_webView loadRequest:request];
關(guān)于userAgent
有時(shí)候應(yīng)服務(wù)端要求塔嬉,需要給webView自定義userAgent玩徊,這里涉及到了html端與后端的獲取,正常獲取邏輯是這樣的
[_webView evaluateJavaScript:"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSString *cusUserAgent = [NSString stringWithFormat:@"%@ %@",result,@"customMethod"];
_webView.customUserAgent = cusUserAgent;
}];
這樣子看起來(lái)似乎沒(méi)什么問(wèn)題谨究,后端可以獲取的到恩袱,但是html端并不可以獲取到已經(jīng)修改后的userAgent,具體原因小生也找不出來(lái)胶哲。畔塔。。
解決辦法
我解決的辦法是鸯屿,創(chuàng)建兩個(gè)webView俩檬,利用其中一個(gè)獲取userAgent,另外一個(gè)在第一個(gè)獲取到的時(shí)候碾盟,使用第一個(gè)的UserAgent,利用第二個(gè)webview進(jìn)行之后的邏輯操作
//注意技竟,這兩個(gè)webview都已經(jīng)初始化冰肴,網(wǎng)上有一些說(shuō)初始化之前調(diào)用,是不可以的。
[_webView1 evaluateJavaScript:@"navigator.userAgent" completionHandler:
^(id _Nullable result, NSError * _Nullable error) {
NSString *cusAgent = [result stringByAppendingString:@"customMethod"];
_webView2.customUserAgent = cusAgent;
}];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
customAgent, @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
[[NSUserDefaults standardUserDefaults] synchronize];
其他
這里記錄一下一些可能會(huì)用到的方法
刪除緩存
- (void)deleteWebCache {
//allWebsiteDataTypes清除所有緩存
NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
}];
}