目前,大多數的應用中都嵌入了H5。那么在iOS應用中如何嵌入一個H5,並且和它進行交互就成了
一個勢必要掌握的技術了。本文我將結合我在項目中的一些需求整理出對應的技術點,僅供參考。
在iOS開發中,H5的嵌入可以通過UIWebView或者WKWebView。這兩個都是繼承UIView,來加載web數據的類。
UIWebView是在iOS2的時候開始使用的。特點是加載速度慢,占用內存多,優化艱難。WKWebView是在iOS8蘋果
新推出的,加載速度快,占用內存較少,是一個不錯的選擇。如果想要比較兩者的區別,您可以選擇一個網頁進行
測試一下。鑒上所述,我們選擇WKWebView進行開發。
- (void)createWebView{
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 根據需要去設置對應的屬性
WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
webView.navigationDelegate = self;
[self.view addSubview:webView];
NSURL *url = [NSURL URLWithString:self.strURL];
[self loadWebViewWithURL:url]; // JS調用OC 添加處理腳本
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
}
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
這是利用WKWebView的一個新特性MessageHandler來處理JS調用原生方法。要實現JS調用iOS原生方法,步驟見下。
添加<WKScriptMessageHandler>協議。讓控制器成為MessageHandler的代理對象。
對於監聽的方法名要和JS開發的人商量好。這里我們監聽的是Share方法,對於JS開發的人員必須要以以下方式寫。
window.webkit.messageHandlers. Share.postMessage(null)
實現協議方法。在這個方法里message參數有一個屬性body。message.body就是JS傳過來的參數,可以是字符串,可以是數組,也可以是字典。通過message.name判斷可以知道監聽的是JS的哪個方法。
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
if ([message.name isEqualToString:@"Share"]) {
//TODO
}
}
至此,JS調用OC代碼就已完結。是不是很簡單。另外,我在網上也看到了不一樣的處理方式。大家可以參考WebViewJavascriptBridge我覺得寫的比較清楚。
[self.webView evaluateJavaScript:@"show()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//TODO
}];
相信代碼已經看得很清楚啦。show()就是JS寫的方法,這個方法可傳可不傳參數,具體依實際情況而定。另外關於UIWebView和JS的交互,以下部分僅供參考。
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"Share"] = ^() {
NSArray *args = [JSContext currentArguments];
dispatch_async(dispatch_get_main_queue(), ^{
//TODO
});
網頁加載開始,結束,失敗這幾個都特別簡單,我就不贅述了。說一下下面這個協議方法,這個方法發生在頁面跳轉中。WKNavigationActionPolicy是一個枚舉,
WKNavigationActionPolicyAllow表示允許跳轉,WKNavigationActionPolicyCancel表示取消跳轉。對了,這里還有一個補充: scrollView嵌套網頁和原生view,原生view要根據網頁的高度來布局。
我看到不少的電商應用都有這種布局,但在算高度上會有各種問題,不知道你們有遇見過?
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSString *url = navigationAction.request.URL.absoluteString;
if(![url isEqualToString:self.strURL]) {
// 頁面跳轉
}
decisionHandler(WKNavigationActionPolicyAllow);
}
不知道您有沒有遇見過JS寫的alert()框在iOS上不彈出。那么您有沒有實現這些協議方法呢。
/// 創建一個新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
/// 輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
/// 確認框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
/// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
這是通過KVO的方式進行監聽的。您可以點擊進WKWebView的內部看一下,他們每個屬性上面都有很長的解釋,你不難發現這一段。舉一個獲取標題的例子。
其他的類似。別忘了,KVO監聽在dealloc中移除監聽者哦。
[self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"title"]) {
if (object == self.webView) {
if(self.navigationController)
self.navigationItem.title = self.webView.title;
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。