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

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

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

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

Copy Bundle Resourses 這里你需要看看有沒有加到這里來。如果這里沒有把文件的引用加進來,Bundle 包里面是找不到這個文件的?!?br>
蘋果官方關于如何查找本地資源的文檔在這里
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 這里會出現(xiàn)錯誤的。
// NSString(contentsOfFile: path!, encoding: String.Encoding.utf8.rawValue
// 下面的這兩個 file 的路徑 調(diào)用方法 等價
// 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代理協(xié)議,
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這個函數(shù)的參數(shù)傳入的值,必須是JS中在全局作用域下能拿到值的函數(shù)或在JS中全局作用域能執(zhí)行的JS語句。
設置webView.navigationDelegate = self ,設置這個代理
javascript 中定義這個函數(shù) addTwoNumbers
var addTwoNumbers = function(swiftObj){
// swiftObj 傳過來的已經(jīng)是一個對象了
window.total = (swiftObj.num1 || 0) + (swiftObj.num2 || 0);
alert("xxx===" + window.total )
return window.total ;
}
swiftObj 這個就是傳過來的數(shù)據(jù)了
調(diào)試JS和頁面?zhèn)髦档男〖记?/h2>
開使用手機App加載 Webview的時候,有時候會遇到 window.xxx 綁定屬性和alert 不顯示彈窗的問題。有個技巧就是講你要處理的數(shù)據(jù)綁定到某個html 頁面的元素屬性上,或者賦值給span 元素的文字上。
同時打開Xcode 和javascript代碼編輯器可以提高效率
代碼提示,代碼片段等等有助于我們編程的東東大多數(shù)和編輯器關聯(lián)。
使用 Xcode 處理iOS . JS代碼編輯器處理網(wǎng)頁,不要只在 Xcode上處理JS.
調(diào)用JS的流程
注意點:
使用Swfit 執(zhí)行javascript 這個方法的時候比較慢。需要使用 swift 傳遞過來的數(shù)據(jù)的時候,需要在webView.evaluateJavaScript(XXX) 中的XXX函數(shù)數(shù)調(diào)用其它的代碼。否則,swift數(shù)據(jù)還沒傳遞過來,其它函數(shù)執(zhí)行了就沒有正確的數(shù)據(jù)了。
JS傳值給Swfit
如何使用javascript 給swift 傳值呢,WKUserContentController 可以做這個事情。
第一步
當前的控制器遵守 協(xié)議:WKScriptMessageHandler
使用WKUserContentController, WKUserContentController可以提供一個add 方法。
WKUserContentController的實例,可以填加 add的方法:
func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
這里面:
WKScriptMessageHandler 就是遵守這個 WKScriptMessageHandler這個協(xié)議的類。在當前控制器這里使用self就可以了。
func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)這個方法實現(xiàn)之后,
window.webkit.messageHandlers.name.postMessage(messageBody)
import UIKit
import WebKit
class UseHardWareViewController: UIViewController,WKScriptMessageHandler{
}
第二步
創(chuàng)建WKWebViewConfiguration的實例,這個實例可以給網(wǎng)頁進行一些配置。注意這個實例只能在 web view第一次創(chuàng)建的時候才能使用?!?br>
WKWebViewConfiguration的實例的一個屬性是WKWebViewConfiguration的實例。
給WKWebViewConfiguration的實例賦值WKWebViewConfiguration的實例。
第三步
使用 WKWebViewConfiguration的實例來創(chuàng)建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里面實現(xiàn)window.webkit.messageHandlers.name.postMessage(messageBody)。
var messageObj = {
'tel':'010-12345678',
'address':'安徽省合肥市濱河西路1200號',
"dictionary": {"name": "foo"},
'name':'fool'
}
window.webkit.messageHandlers.foo.postMessage(messageObj)
第五步
實現(xiàn)這個方法 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頁面跳轉(zhuǎn)處理
extension UseHardWareViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("webView===\(webView.url!)")
}
}
遵守這個協(xié)議WKNavigationDelegate后, 每次導航結束后都會有打印。
在WKWebView加載了網(wǎng)頁之后,對網(wǎng)頁進行更改
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:) 代碼方法中實現(xiàn),頁面跳轉(zhuǎn)完成之后實現(xiàn)更改網(wǎng)頁中的圖片尺寸。
不同帳號進入相同內(nèi)容詳情
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 的頁面,本地有緩存,就請求緩存,沒有再去請求。
例如新聞詳情這樣的不更改內(nèi)容的靜態(tài)網(wǎng)頁就可以使用這個方式來加載。
這個網(wǎng)頁加載的方式的優(yōu)點是省流量:
網(wǎng)頁的內(nèi)容包括(圖片)都可以緩存。