Swift 中使用WKWebview的開發記錄

把網頁相關的文件打包到APP中

把網頁相關文件打包到App中會加快一些js和css文件的加載速度(個人認為,不用耗流量去請求了)

這里的注意點:

image.png

Resourse 文件夾放到這里  Resourse 顯示成黃色文件夾

image.png

自己定義的文件夾,需要填加成藍色文件夾

image.png

folder references 這里就是藍色的文件夾

image.png

Copy Bundle Resourses 這里你需要看看有沒有加到這里來。如果這里沒有把文件的引用加進來,Bundle 包里面是找不到這個文件的。 
蘋果官方關于如何查找本地資源的文檔在這里

For more details on how localized resources are found, read The Bundle Search Pattern in Bundle Programming Guide

.

相關加載代碼

      let path = Bundle.main.path(forResource: "view1/html/recordMaterial", ofType: "html")
        let basePath  = (path! as NSString).deletingLastPathComponent
        do{
            // 這里可能會拋出錯誤,, try 這里會出現錯誤的。
            //  NSString(contentsOfFile: path!, encoding: String.Encoding.utf8.rawValue
            // 下面的這兩個 file    的路徑 調用方法 等價
//            let htmlString = ( try NSString(contentsOfFile: path!, encoding: String.Encoding.utf8.rawValue) ) as String
            let htmlString =  try String(contentsOfFile: path!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
            webView.loadHTMLString(htmlString, baseURL:NSURL(fileURLWithPath: basePath) as URL)
        }catch{
            print(error)
        }

注意: forResource: "view1/html/recordMaterial"  這里的路徑要替換成你自己的。

WKWebView 中alert(jsString) 不顯示的問題

Swift 的代碼中,當前加載WKWebview的 Controller遵守WKUIDelegate代理協議,
wkWebviewInstance..uiDelegate = self , 這里的 self 就是當前的 Controller .

copy 一下 代碼::

// WKUIDelegate
    // 用于 WkWebView 上面  使用 alert 彈窗 結束
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping () -> Void) {
        
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler()
        }))
        
        present(alertController, animated: true, completion: nil)
    }
    
    
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping (Bool) -> Void) {
        
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
        
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler(true)
        }))
        
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            completionHandler(false)
        }))
        
        present(alertController, animated: true, completion: nil)
    }
    
    
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping (String?) -> Void) {
        
        let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)
        
        alertController.addTextField { (textField) in
            textField.text = defaultText
        }
        
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            if let text = alertController.textFields?.first?.text {
                completionHandler(text)
            } else {
                completionHandler(defaultText)
            }
        }))
        
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            completionHandler(nil)
        }))
        
        present(alertController, animated: true, completion: nil)
    }
    // 用于 WkWebView 上面  使用 alert 彈窗 結束

我自己試驗了一下,WKUIDelegate將JS的彈窗效果展示除了原生iOS的彈窗效果。

WKWebView 傳值給 js.

給當前的controller 加一個擴展


extension RecordMaterialViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let dict = [
            "num1": 4,
            "num2": 8
        ]
        let jsonData = try! JSONSerialization.data(withJSONObject: dict, options: [])
        let jsonString = String(data: jsonData, encoding: String.Encoding.utf8)!
        webView.evaluateJavaScript("addTwoNumbers(\(jsonString));")  { (result, error) in
            guard error == nil else {
                print("there was an error")
                print("error === \(String(describing: error))")
                return
            }
            print("結果是\(result)")
        }
    }
}

Note: evaluateJavaScript這個函數的參數傳入的值,必須是JS中在全局作用域下能拿到值的函數或在JS中全局作用域能執行的JS語句。

設置webView.navigationDelegate = self ,設置這個代理

javascript 中定義這個函數 addTwoNumbers


 var addTwoNumbers = function(swiftObj){
            // swiftObj   傳過來的已經是一個對象了
            window.total = (swiftObj.num1 || 0) + (swiftObj.num2 || 0);
            alert("xxx===" + window.total )
            return window.total ;
          }

swiftObj 這個就是傳過來的數據了

調試JS和頁面傳值的小技巧

開使用手機App加載 Webview的時候,有時候會遇到 window.xxx 綁定屬性和alert 不顯示彈窗的問題。有個技巧就是講你要處理的數據綁定到某個html 頁面的元素屬性上,或者賦值給span 元素的文字上。

同時打開Xcodejavascript代碼編輯器可以提高效率

代碼提示,代碼片段等等有助于我們編程的東東大多數和編輯器關聯。
使用 Xcode 處理iOS . JS代碼編輯器處理網頁,不要只在 Xcode上處理JS.

調用JS的流程

注意點: 
   使用Swfit 執行javascript 這個方法的時候比較慢。需要使用 swift 傳遞過來的數據的時候,需要在webView.evaluateJavaScript(XXX) 中的XXX函數數調用其它的代碼。否則,swift數據還沒傳遞過來,其它函數執行了就沒有正確的數據了。

JS傳值給Swfit

如何使用javascriptswift 傳值呢,WKUserContentController 可以做這個事情。

第一步

當前的控制器遵守 協議:WKScriptMessageHandler
使用WKUserContentController, WKUserContentController可以提供一個add 方法。
WKUserContentController的實例,可以填加 add的方法:
func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
這里面: 
WKScriptMessageHandler 就是遵守這個 WKScriptMessageHandler這個協議的類。在當前控制器這里使用self就可以了。
func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)這個方法實現之后,
window.webkit.messageHandlers.name.postMessage(messageBody)

import UIKit
import WebKit

class UseHardWareViewController: UIViewController,WKScriptMessageHandler{

}

第二步

創建WKWebViewConfiguration的實例,這個實例可以給網頁進行一些配置。注意這個實例只能在 web view第一次創建的時候才能使用。 
WKWebViewConfiguration的實例的一個屬性是WKWebViewConfiguration的實例。
WKWebViewConfiguration的實例賦值WKWebViewConfiguration的實例。

第三步

使用 WKWebViewConfiguration的實例來創建webView, 并且將webView 添加到當前的控制器的視圖上。

        let o = WKUserContentController()
        o.add(self, name: "foo")
        let config = WKWebViewConfiguration()
        config.userContentController = o
        webView = WKWebView.init(frame: view.bounds, configuration: config)
        self.view.addSubview(webView)

第四步

JS里面實現window.webkit.messageHandlers.name.postMessage(messageBody)

  var messageObj = {
    'tel':'010-12345678',
    'address':'安徽省合肥市濱河西路1200號',
    "dictionary": {"name": "foo"},
    'name':'fool'
  }
  
  window.webkit.messageHandlers.foo.postMessage(messageObj)

第五步

實現這個方法 swift 里面:
 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)

 /// Js 給 Swift 傳值
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage){
        let body = message.body
        print("body===\(body)")
        if let dict = body as? Dictionary<String, AnyObject> {
            print("dict====\(dict)");
            print("message====\(message)");
            print(message.name)
            if(message.name == "foo"){
                let value = String(describing: dict["name"]!)
                print("body.name: \(value)")
            }
        }
        
    }

打印結果是

body.name: fool

JS 給 Swift 傳值就打通了。

WKWebView中web頁面跳轉處理

extension UseHardWareViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("webView===\(webView.url!)")

    }
}

遵守這個協議WKNavigationDelegate后, 每次導航結束后都會有打印。

WKWebView加載了網頁之后,對網頁進行更改

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
       let  modifyImagesJS =
            "var images = document.getElementsByTagName('img');" +
            "for(var i = 0; i < images.length; i++) {" +
            "images[i].removeAttribute(\"height\");" +
            "images[i].style.height = \"auto\";" +
            "images[i].style.maxWidth = window.innerWidth - 20 * 2;" + 
            "}"
        
        webView.evaluateJavaScript(modifyImagesJS)  { (result, error) in
            guard error == nil else {
                print("there was an error")
                print("error === \(String(describing: error))")
                return
            }
            print("結果是\(result)")
        }
    }

在WKNavigationDelegate中的webView(_:didFinish:) 代碼方法中實現,頁面跳轉完成之后實現更改網頁中的圖片尺寸。

不同帳號進入相同內容詳情


 let url = NSURL(string:"**YourWebPath**");        
        
let request = NSURLRequest.init(url:url! as URL, cachePolicy:NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 10.0)
        
webView.load(request as URLRequest)

returnCacheDataElseLoad 使用的比較多:

Swift4
Specifies that the existing cached data should be used to satisfy the request, regardless of its age or expiration date. If there is no existing data in the cache corresponding the request, the data is loaded from the originating source.

大意就是如果這個請求的URL 的頁面,本地有緩存,就請求緩存,沒有再去請求。
例如新聞詳情這樣的不更改內容的靜態網頁就可以使用這個方式來加載。
這個網頁加載的方式的優點是省流量:
網頁的內容包括(圖片)都可以緩存。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,172評論 4 61
  • 雖然WKWebView是在Apple的WWDC 2014隨iOS 8和OS X 10.10出來的,是為了解決UIW...
    winann閱讀 136,078評論 195 641
  • 雖然我寫作還只是起步,但是我覺得這段時間的練習,有兩條比較實用的經驗。1剛開始可能下筆很困難,就告訴自己先隨便寫寫...
    佐江閱讀 760評論 0 0
  • “嘶,痛,不對,我不是死了嗎?” 栗罌吃力地睜開雙眼第一個看到的人是一個穿著古代衣服的小姑娘,小姑娘邊哭邊說:“小...
    破曉的黎閱讀 350評論 0 0
  • 哇,今天的書是《習慣的力量》!這本書在我電子書上閱讀了一半就擱置了,前陣子聽指南針老師的分享,然后又是今天晨讀。是...
    云棫閱讀 210評論 2 2