要掌握iOS與JS交互阐滩,首先一定要掌握的就是,iOS的h5容器UIWebView和WKWebView,下面我們就分別來說說他們的用法和優(yōu)劣逾滥。
一、概述
??UIWebView自iOS2就有,WKWebView從iOS8才有寨昙,毫無疑問WKWebView將逐步取代UIWebView讥巡。WKWebView只能用代碼創(chuàng)建,而且自身就支持了右滑返回手勢(shì)allowsBackForwardNavigationGestures和加載進(jìn)度estimatedProgress等一些UIWebView不具備卻非常好用的屬性舔哪。通過簡單的測(cè)試即可發(fā)現(xiàn)UIWebView占用過多內(nèi)存欢顷。WKWebView網(wǎng)頁加載速度也有提升,但是并不像內(nèi)存那樣提升那么多捉蚤。下面列舉一些其它的優(yōu)勢(shì):
- 更多的支持HTML5的特性
- 官方宣稱的高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢(shì)
- 與Safari相同的JavaScript引擎
- 將UIWebViewDelegate與UIWebView拆分成了14類與3個(gè)協(xié)議(官方文檔說明)
- 另外用的比較多的抬驴,增加加載進(jìn)度屬性:estimatedProgress
UIWebView用法
1、加載網(wǎng)頁或本地文件
UIWebView *webView = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
webView.delegate = self;
[self.view addSubview:webView];
// 網(wǎng)頁url
// NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
// 本地文件
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *url = [NSURL fileURLWithPath:path];
// 網(wǎng)絡(luò)請(qǐng)求
NSURLRequest *request =[NSURLRequest requestWithURL:url];
// 加載網(wǎng)頁
[self.webview loadRequest:request];
2缆巧、UIWebView的對(duì)象方法
// 加載Data數(shù)據(jù)創(chuàng)建一個(gè)webView
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
// 加載本地HTML創(chuàng)建一個(gè)webView
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
// 加載一個(gè)請(qǐng)求創(chuàng)建一個(gè)webView
- (void)loadRequest:(NSURLRequest *)request
// 刷新網(wǎng)頁
- (void)reload;
// 停止加載
- (void)stopLoading;
// 后退函數(shù)
- (void)goBack;
// 前進(jìn)函數(shù)
- (void)goForward;
// 執(zhí)行JS方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
3布持、UIWebView的屬性 :
// 代理屬性 重點(diǎn)需要知道代理方法的使用
@property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;
// 這個(gè)是webView內(nèi)部的scrollView 只讀,但是利用這個(gè)屬性,設(shè)置scrollView的代理,就可以控制整個(gè)webView的滾動(dòng)事件
@property(nonatomic, readonly, strong) UIScrollView *scrollView;
// webView的請(qǐng)求,這個(gè)屬性一般在整個(gè)加載完成后才能拿到
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;
// 如果這個(gè)屬性為YES,才能后退
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
// 如果這個(gè)屬性為YES,才能前進(jìn)
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
// 這個(gè)屬性很好用,如果為YES證明webView還在加載數(shù)據(jù),所有數(shù)據(jù)加載完畢后,webView就會(huì)為No
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
// YES代表網(wǎng)頁可以縮放,NO代表不可以縮放
@property (nonatomic) BOOL scalesPageToFit;
// 設(shè)置某些數(shù)據(jù)變?yōu)殒溄有问剑@個(gè)枚舉可以設(shè)置如電話號(hào)陕悬,地址题暖,郵箱等轉(zhuǎn)化為鏈接
@property (nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);
// 設(shè)置是否使用內(nèi)聯(lián)播放器播放視頻
@property (nonatomic) BOOL allowsInlineMediaPlayback NS_AVAILABLE_IOS(4_0);
// 設(shè)置視頻是否自動(dòng)播放
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction NS_AVAILABLE_IOS(4_0);
// 設(shè)置音頻播放是否支持ari play功能
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay NS_AVAILABLE_IOS(5_0);
// 設(shè)置是否將數(shù)據(jù)加載入內(nèi)存后渲染界面
@property (nonatomic) BOOL suppressesIncrementalRendering NS_AVAILABLE_IOS(6_0);
// 設(shè)置用戶是否能打開keyboard交互
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS(6_0);
/* IOS7 */ 以后的新特性
// 這個(gè)屬性用來設(shè)置一種模式,當(dāng)網(wǎng)頁的大小超出view時(shí)捉超,將網(wǎng)頁以翻頁的效果展示芙委,枚舉如下:
@property (nonatomic) UIWebPaginationMode paginationMode NS_AVAILABLE_IOS(7_0);
typedef NS_ENUM(NSInteger, UIWebPaginationMode) {
UIWebPaginationModeUnpaginated, //不使用翻頁效果
UIWebPaginationModeLeftToRight, //將網(wǎng)頁超出部分分頁,從左向右進(jìn)行翻頁
UIWebPaginationModeTopToBottom, //將網(wǎng)頁超出部分分頁狂秦,從上向下進(jìn)行翻頁
UIWebPaginationModeBottomToTop, //將網(wǎng)頁超出部分分頁灌侣,從下向上進(jìn)行翻頁
UIWebPaginationModeRightToLeft //將網(wǎng)頁超出部分分頁,從右向左進(jìn)行翻頁
};
// 這個(gè)屬性決定CSS的屬性分頁是可用還是忽略裂问。默認(rèn)是UIWebPaginationBreakingModePage
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode NS_AVAILABLE_IOS(7_0);
// 設(shè)置每一頁的長度
@property (nonatomic) CGFloat pageLength NS_AVAILABLE_IOS(7_0);
// 設(shè)置每一頁的間距
@property (nonatomic) CGFloat gapBetweenPages NS_AVAILABLE_IOS(7_0);
// 獲取頁數(shù)
@property (nonatomic, readonly) NSUInteger pageCount NS_AVAILABLE_IOS(7_0);
4侧啼、相關(guān)代理協(xié)議
#pragma mark - UIWebViewDelegate
// 請(qǐng)求發(fā)送前都會(huì)調(diào)用該方法,返回NO則不處理這個(gè)請(qǐng)求,不加載網(wǎng)頁
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(@"允許加載網(wǎng)頁");
return YES;
}
// 請(qǐng)求發(fā)送之后開始接收響應(yīng)之前會(huì)調(diào)用這個(gè)方法
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(@"開始加載網(wǎng)頁");
}
// 請(qǐng)求發(fā)送之后,并且服務(wù)器已經(jīng)返回響應(yīng)之后調(diào)用該方法
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(@"網(wǎng)頁加載完成");
}
// 網(wǎng)頁請(qǐng)求失敗則會(huì)調(diào)用該方法
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"網(wǎng)頁加載錯(cuò)誤時(shí)調(diào)用");
}
5、OC調(diào)用JS方法
OC調(diào)用JS函數(shù)主要通過下面方法:
- (nullable NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;
例:
[self.webView stringByEvaluatingJavaScriptFromString:@"alertMobile()"];
調(diào)用這個(gè)方法需要在網(wǎng)頁加載完成之后堪簿,因?yàn)檫@個(gè)時(shí)候整個(gè)html頁面包括js/css已經(jīng)注入到webView中痊乾,此時(shí)調(diào)用方法才會(huì)有響應(yīng),相反網(wǎng)頁加載完成之前調(diào)用界面不會(huì)有任何響應(yīng)
6椭更、JS調(diào)用OC方法
??JS是不能執(zhí)行OC代碼的哪审,但是可以變相的執(zhí)行,JS可以將要執(zhí)行的操作封裝到網(wǎng)絡(luò)請(qǐng)求里面虑瀑,然后OC攔截這個(gè)請(qǐng)求湿滓,獲取URL里面的字符串解析即可,這里用到代理協(xié)議的如下方法:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
有了上面的方法后舌狗,很顯然叽奥,想要JS調(diào)用OC我們就可以采用在按鈕點(diǎn)擊的后重定向一個(gè)URL,這個(gè)URL攜帶OC的方法名及參數(shù)信息痛侍,然后在這個(gè)方法中拿到對(duì)應(yīng)的URL朝氓,對(duì)URL進(jìn)行解析,提取對(duì)應(yīng)的方法名和參數(shù)信息,調(diào)用OC相應(yīng)的方法赵哲,從而實(shí)現(xiàn)了交互的可能
iiooss://showSendNumber_msg_?13300001111&這個(gè)周末去爬山
在這個(gè)URL中前面的"iiooss://"是URL的scheme待德,通過這個(gè)來提取我們關(guān)心的URL,對(duì)其他URL不做任何處理枫夺,后面就是OC方法和參數(shù)的信息了将宪,這里用"?"來分割分割方法名和參數(shù),"&"來分割多個(gè)參數(shù)筷屡,"_"用作OC方法名中冒號(hào)的替換涧偷。
例:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
// 獲取請(qǐng)求路徑
NSString *urlString = [[request URL] absoluteString];
// 解碼
urlString = [urlString stringByRemovingPercentEncoding];
// 定義的協(xié)議
NSString *scheme = @"iiooss://";
if ([urlString hasPrefix:scheme]) {
// 獲得協(xié)議后面的路徑
NSString *subPath = [urlString substringFromIndex:scheme.length];
if ([subPath containsString:@"?"]) {
// 利用?切割路徑 分割方法與參數(shù)
NSArray *components = [subPath componentsSeparatedByString:@"?"];
// 方法名
NSString *methodName = [components firstObject];
methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
// 參數(shù)
NSString *parameter = [components lastObject];
NSArray *params = [parameter componentsSeparatedByString:@"&"];
/// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn)簸喂,
/// 也可以考慮:- (id)performSelector:(SEL)aSelector;
/// 或者NSInvocation
}
else
{
NSString *methodName = [subPath stringByReplacingOccurrencesOfString:@"_" withString:@":"];
/// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn)毙死,
/// 也可以考慮:- (id)performSelector:(SEL)aSelector;
/// 或者NSInvocation
}
}
return YES;
}
7、緩存
??盡量使用 GET 請(qǐng)求喻鳄,iOS 系統(tǒng) SDK 會(huì)自動(dòng)幫你做緩存扼倘。你需要的僅僅是設(shè)置下內(nèi)存緩存大小、磁盤緩存大小除呵、以及緩存路徑再菊。只要設(shè)置了這兩行代碼,基本就可滿足80%的緩存需求颜曾。
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
WKWebView的用法
Classes:
WKBackForwardList: 之前訪問過的 web 頁面的列表纠拔,可以通過后退和前進(jìn)動(dòng)作來訪問到。
WKBackForwardListItem: webview 中后退列表里的某一個(gè)網(wǎng)頁泛豪。
WKFrameInfo: 包含一個(gè)網(wǎng)頁的布局信息稠诲。
WKNavigation: 包含一個(gè)網(wǎng)頁的加載進(jìn)度信息。
WKNavigationAction: 包含可能讓網(wǎng)頁導(dǎo)航變化的信息诡曙,用于判斷是否做出導(dǎo)航變化臀叙。
WKNavigationResponse: 包含可能讓網(wǎng)頁導(dǎo)航變化的返回內(nèi)容信息,用于判斷是否做出導(dǎo)航變化价卤。
WKPreferences: 概括一個(gè) webview 的偏好設(shè)置劝萤。
WKProcessPool: 表示一個(gè) web 內(nèi)容加載池。
WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法慎璧。
WKScriptMessage: 包含網(wǎng)頁發(fā)出的信息床嫌。
WKUserScript: 表示可以被網(wǎng)頁接受的用戶腳本。
WKWebViewConfiguration: 初始化 webview 的設(shè)置胸私。
WKWindowFeatures: 指定加載新網(wǎng)頁時(shí)的窗口屬性既鞠。
Protocols
WKNavigationDelegate: 提供了追蹤主窗口網(wǎng)頁加載過程和判斷主窗口和子窗口是否進(jìn)行頁面加載新頁面的相關(guān)方法。
WKScriptMessageHandler: 提供從網(wǎng)頁中收消息的回調(diào)方法盖文。
WKUIDelegate: 提供用原生控件顯示網(wǎng)頁的方法回調(diào)嘱蛋。
1、加載網(wǎng)頁或本地文件
WKWebView *webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.view addSubview:webView];
// 網(wǎng)頁url
// NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
// 網(wǎng)絡(luò)請(qǐng)求
// NSURLRequest *request =[NSURLRequest requestWithURL:url];
// 加載網(wǎng)頁
// [webView loadRequest:request];
// 創(chuàng)建url
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
// 創(chuàng)建URL
NSURL *url = [NSURL fileURLWithPath:path];
// 加載文件
[webView loadFileURL:url allowingReadAccessToURL:url];
self.webView = webView;
2、WKWebView的對(duì)象方法
// 這是加載網(wǎng)頁最常用的一種方式洒敏,通過一個(gè)網(wǎng)頁URL來加載一個(gè)WKWebView龄恋,這個(gè)URL可以是遠(yuǎn)程的也可以是本地的,例如我加載百度的主頁
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
// 根據(jù)一個(gè)文件,加載一個(gè)WKWebView
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);
// 這個(gè)方法需要將html文件讀取為字符串從而加載為WKWebView凶伙,其中baseURL是我們自己設(shè)置的一個(gè)路徑郭毕,用于尋找html文件中引用的圖片等素材。
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
// 這個(gè)方式使用的比較少函荣,但也更加自由显押,其中data是文件數(shù)據(jù),MIMEType是文件類型傻挂,characterEncodingName是編碼類型乘碑,baseURL是素材資源路徑
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0);
3、WKWebView的屬性
// UIWebView 中會(huì)自動(dòng)保存Cookie金拒,如果登錄了一次下次再次進(jìn)入的時(shí)候,會(huì)記住登錄狀態(tài)
// 在WKWebView中兽肤,新增一個(gè)configuration屬性, configuration 讓W(xué)KWebView知道登錄狀態(tài),
// configuration 可以通過已有的Cookie進(jìn)行設(shè)置绪抛,也可以通過保存上一次的configuration進(jìn)行設(shè)置
// WKWebViewConfiguration類中也有一些相應(yīng)的屬性
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
// WKWebView中,加入了網(wǎng)站導(dǎo)航的概念,這個(gè)對(duì)象決定主框架導(dǎo)航加載方法協(xié)議资铡。
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;
// WKWebView中,加入了網(wǎng)站窗口的概念,這個(gè)對(duì)象決了webView窗口的一些方法協(xié)議。
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;
// WKWebView中,加入了網(wǎng)站列表的概念,這個(gè)WEBBackForwardList對(duì)象是以前在Web視圖訪問的網(wǎng)頁幢码,可以通過去后退或前進(jìn)
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
4笤休、WKWebView的代理方法
/**
* web內(nèi)容處理中斷時(shí)會(huì)觸發(fā)
* 當(dāng) WKWebView 總體內(nèi)存占用過大,頁面即將白屏的時(shí)候症副,系統(tǒng)會(huì)調(diào)用上面的回調(diào)函數(shù)店雅,我們?cè)谠摵瘮?shù)里執(zhí)行[webView reload](這個(gè)時(shí)候 webView.URL 取值尚不為 nil)解決白屏問題。
*/
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"webViewWebContentProcessDidTerminate: 當(dāng)Web視圖的網(wǎng)頁內(nèi)容被終止時(shí)調(diào)用瓦糕。");
}
/**
* 頁面加載完成底洗。 等同于UIWebViewDelegate: - webViewDidFinishLoad:
*
* @param webView
* @param navigation
*/
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(@"webView:didFinishNavigation: 響應(yīng)渲染完成后調(diào)用該方法 webView : %@ -- navigation : %@ \n\n",webView,navigation);
}
/**
* 準(zhǔn)備加載頁面。等同于UIWebViewDelegate: - webView:shouldStartLoadWithRequest:navigationType
*
* @param webView
* @param navigation
*/
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSLog(@"webView:didStartProvisionalNavigation: 開始請(qǐng)求 \n\n");
}
/**
* 內(nèi)容開始加載. 等同于UIWebViewDelegate: - webViewDidStartLoad:
*
* @param webView
* @param navigation
*/
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(@"webView:didCommitNavigation: 響應(yīng)的內(nèi)容到達(dá)主頁面的時(shí)候響應(yīng),剛準(zhǔn)備開始渲染頁面應(yīng)用 \n\n");
}
/**
* 頁面加載失敗時(shí)調(diào)用
*/
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
// 類似 UIWebView 的- webView:didFailLoadWithError:
NSLog(@"webView:didFailProvisionalNavigation:withError: 啟動(dòng)時(shí)加載數(shù)據(jù)發(fā)生錯(cuò)誤就會(huì)調(diào)用這個(gè)方法咕娄。 \n\n");
}
/**
* 頁面加載失敗亥揖。 等同于UIWebViewDelegate: - webView:didFailLoadWithError:
*
* @param webView
* @param navigation
* @param error
*/
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"webView:didFailNavigation: 當(dāng)一個(gè)正在提交的頁面在跳轉(zhuǎn)過程中出現(xiàn)錯(cuò)誤時(shí)調(diào)用這個(gè)方法。 \n\n");
}
/**
* 根據(jù)webView圣勒、navigationAction相關(guān)信息決定這次跳轉(zhuǎn)是否可以繼續(xù)進(jìn)行,這些信息包含HTTP發(fā)送請(qǐng)求费变,如頭部包含User-Agent,Accept,refer
* 在發(fā)送請(qǐng)求之前,決定是否跳轉(zhuǎn)的代理
* @param webView
* @param navigationAction
* @param decisionHandler
*/
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSLog(@"請(qǐng)求前會(huì)先進(jìn)入這個(gè)方法 webView:decidePolicyForNavigationActiondecisionHandler: %@ \n\n ",navigationAction.request);
decisionHandler(WKNavigationActionPolicyAllow);
}
/**
* 這個(gè)代理方法表示當(dāng)客戶端收到服務(wù)器的響應(yīng)頭圣贸,根據(jù)response相關(guān)信息挚歧,可以決定這次跳轉(zhuǎn)是否可以繼續(xù)進(jìn)行。
* 在收到響應(yīng)后吁峻,決定是否跳轉(zhuǎn)的代理
* @param webView
* @param navigationResponse
* @param decisionHandler
*/
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
NSLog(@"返回響應(yīng)前先會(huì)調(diào)用這個(gè)方法 并且已經(jīng)能接收到響應(yīng)webView:decidePolicyForNavigationResponse:decisionHandler: Response?%@ \n\n",navigationResponse.response);
decisionHandler(WKNavigationResponsePolicyAllow);
}
/**
* 這個(gè)代理是服務(wù)器redirect時(shí)調(diào)用
* 接收到服務(wù)器跳轉(zhuǎn)請(qǐng)求的代理
* @param webView
* @param navigation
*/
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"webView:didReceiveServerRedirectForProvisionalNavigation: 重定向的時(shí)候就會(huì)調(diào)用 \n\n");
}
WKScriptMessageHandler:必須實(shí)現(xiàn)的函數(shù)滑负,是APP與js交互在张,提供從網(wǎng)頁中收消息的回調(diào)方法
// 是js與APP交互,提供從網(wǎng)頁中收消息的回調(diào)方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
與JS的alert矮慕、confirm帮匾、prompt交互,我們希望用自己的原生界面痴鳄,而不是JS的瘟斜,就可以使用這個(gè)代理類來實(shí)現(xiàn)。
// 新開一個(gè)WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
// prompt 輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
// confirm 確認(rèn)框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
// alert 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
5痪寻、網(wǎng)頁導(dǎo)航刷新有關(guān)函數(shù)
@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward;
- (WKNavigation *)goBack;
- (WKNavigation *)goForward;
- (WKNavigation *)reload;
- (WKNavigation *)reloadFromOrigin; // 增加的函數(shù)
- (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; // 增加的函數(shù)
- (void)stopLoading;
reloadFromOrigin會(huì)比較網(wǎng)絡(luò)數(shù)據(jù)是否有變化螺句,沒有變化則使用緩存,否則從新請(qǐng)求橡类。
goToBackForwardListItem:比向前向后更強(qiáng)大蛇尚,可以跳轉(zhuǎn)到某個(gè)指定歷史頁面
6、一些常用屬性
allowsBackForwardNavigationGestures:BOOL類型猫态,是否允許左右劃手勢(shì)導(dǎo)航佣蓉,默認(rèn)不允許
estimatedProgress:加載進(jìn)度披摄,取值范圍0~1
title:頁面title
scrollView.scrollEnabled:是否允許上下滾動(dòng)亲雪,默認(rèn)允許
backForwardList:WKBackForwardList類型,訪問歷史列表疚膊,可以通過前進(jìn)后退按鈕訪問义辕,或者通過goToBackForwardListItem函數(shù)跳到指定頁面
7、JS調(diào)用OC
index.html:
// 內(nèi)聯(lián)事件寓盗、腳本事件或DOM事件調(diào)用此函數(shù)
function onClickButton() {
// JS通知WKWebView
window.webkit.messageHandlers.senderModel.postMessage("參數(shù)");
}
// webview的相關(guān)配置
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
// 初始化偏好設(shè)置屬性:preferences
config.preferences = [WKPreferences new];
// 默認(rèn)值中的最小字體大小是0
config.preferences.minimumFontSize = 10;
// 是否支持JavaScript
config.preferences.javaScriptEnabled = YES;
// 不通過用戶交互灌砖,是否可以打開窗口
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
// js配置---通過JS與webView內(nèi)容交互
config.userContentController = [WKUserContentController new];
// js通過senderModel來調(diào)用
[config.userContentController addScriptMessageHandler:self name:@"senderModel"];
WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
NSURL *path = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:path]];
[self.view addSubview:webView];
self.webView = webView;
響應(yīng):
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"方法名:%@", message.name);
NSLog(@"參數(shù):%@", message.body);
// 方法名
NSString *methods = [NSString stringWithFormat:@"%@:", message.name];
/// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn),
/// 也可以考慮:- (id)performSelector:(SEL)aSelector;參數(shù)以字面量對(duì)象形式
/// 或者NSInvocation
}
8傀蚌、OC調(diào)用JS
oc調(diào)用js就特別簡單了基显,只需WKWebView調(diào)用下面方法即可。
NSString *jsActionStr = [NSString stringWithFormat:@"actionName('%@')", @"參數(shù)"];
[self.webView evaluateJavaScript:jsActionStr completionHandler:^(id _Nullable data, NSError * _Nullable error) {
if (error) {
NSLog(@"錯(cuò)誤:%@", error.localizedDescription);
}
}];
響應(yīng):
index.html:
// 函數(shù)
function actionName(params) {
document.getElementById('spanId').innerHTML = params;
}
9善炫、WKUserScript JS注入
??在WebKit框架中撩幽,我們還可以預(yù)先添加JS方法,供其ta人員調(diào)用箩艺。WKUserScript就是幫助我們完成JS注入的類窜醉,它能幫助我們?cè)陧撁嫣畛淝盎騤s填充完成后調(diào)用。
WKUserScript核心方法:
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
在WKUserScriptInjectionTime枚舉中有兩個(gè)狀態(tài):
1. WKUserScriptInjectionTimeAtDocumentStart:js加載前執(zhí)行艺谆。
2. WKUserScriptInjectionTimeAtDocumentEnd:js加載后執(zhí)行榨惰。
10、歷史記錄
// 查詢歷史記錄
WKBackForwardList *backForwardList = self.webView.backForwardList;
暫時(shí)先這么多吧静汤,以后想起什么再補(bǔ)充琅催,都是些簡單的應(yīng)用居凶,具體實(shí)現(xiàn)根據(jù)具體情況而定,寫程序不要寫死藤抡,靈活應(yīng)用方為上策排监,這里呢也算一個(gè)小的總結(jié)吧,避免重復(fù)造輪子杰捂。