WKWebView确实从本地文档文件夹加载资源

Pet*_*ter 31 ios swift wkwebview

在我的Swift iOS应用程序中,我想从远程服务器下载一些动态HTML页面,将它们保存在文档目录中,并从文档目录中显示这些页面.

我用它来加载页面:

var appWebView:WKWebView?
...
appWebView!.loadRequest(NSURLRequest(URL: NSURL(fileURLWithPath: htmlPath)))
Run Code Online (Sandbox Code Playgroud)

一切都在模拟器上运行,但当我转移到真正的手机时,它只是显示一个空白页面.然后我使用Safari连接到应用程序,发现它抱怨"无法加载资源".

然后我尝试先阅读页面内容htmlPath,然后使用

appWebView!.loadHTMLString()
Run Code Online (Sandbox Code Playgroud)

加载页面.它在HTML页面很简单时有效.但是,如果HTML引用其他内容,即文档目录中的JavaScript文件(具有绝对路径<script src="file:////var/mobile/Containers/Data/Application/762035C9-2BF2-4CDD-B5B1-574A0E2B0728/Documents/xxxxx.js">),则无法加载.

有谁知道为什么会这样,以及如何解决这个问题?

更多信息:

  • XCode版本:7.3.1
  • 部署目标:8.1(我也尝试使用9.3,但这没有帮助.)

tec*_*242 34

这是我用来加载我的项目中的本地文件(iOS 10,Swift 3)的简化版本.我根据Raghuram和Fox5150在评论中的要求,在iOS 10.3.1和iPhone 7+上再次测试后,我刚刚更新了我的代码(7.5.2017).

我刚刚创建了一个全新的项目,这是文件夹结构:在此输入图像描述

更新19.04.2018:添加了一个新功能,用HTML,CSS,JS文件下载.zip,将其解压缩到/ Documents /(Alamofire + Zip),然后将这些文件加载​​到webView中.您也可以在GitHub示例项目中找到它.再次,随意分叉和明星!:)

更新08.02.2018:最后添加了一个GitHub示例项目,该项目还包含一个本地JavaScript文件.随意分叉和明星!:)

带有webView.loadFileURL()的版本1

ViewController.swift

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        let webView = WKWebView()
        let htmlPath = Bundle.main.path(forResource: "index", ofType: "html")
        let htmlUrl = URL(fileURLWithPath: htmlPath!, isDirectory: false)
        webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl)
        webView.navigationDelegate = self
        view = webView
    }
}
Run Code Online (Sandbox Code Playgroud)

带有webView.loadHTMLString()的版本2

ViewController.swift

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        let webView = WKWebView()
        let htmlPath = Bundle.main.path(forResource: "index", ofType: "html")
        let folderPath = Bundle.main.bundlePath
        let baseUrl = URL(fileURLWithPath: folderPath, isDirectory: true)
        do {
            let htmlString = try NSString(contentsOfFile: htmlPath!, encoding: String.Encoding.utf8.rawValue)
             webView.loadHTMLString(htmlString as String, baseURL: baseUrl)
        } catch {
            // catch error
        }
        webView.navigationDelegate = self
        view = webView
    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意:

  • 确保您的本地html/js/css文件位于Project - > Target - > Build Phases - > Copy Bundle Resources
  • 确保您的html文件不引用相对路径,例如css/styles.css因为iOS将展平您的文件结构,而styles.css将与index.html处于同一级别,因此请<link rel="stylesheet" type="text/css" href="styles.css">改为编写

鉴于这两个版本,这里的问题是我的项目中的html/css文件:

网络/ index.html的

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    <title>Offline WebKit</title>
    <link rel="stylesheet" type="text/css" href="styles.css">
  </head>
  <body>
    <h1 id="webkit-h1">Offline WebKit!</h1>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

网络/ CSS/Styles.css中

#webkit-h1 {
  font-size: 80px;
  color: lightblue;
}
Run Code Online (Sandbox Code Playgroud)

如果有人想要一个GitHub示例项目,请在评论部分告诉我,我会上传它.

  • @ tech4242很棒的答案!您还可以通过使用文件夹引用添加资源来支持html/css/js中的子文件夹引用.您只需在Xcode中的项目结构中拖动html assets文件夹,然后选择**"创建文件夹引用"**.然后,您可以通过执行以下操作访问整个资产目录结构:(假设您的文件夹名为**HtmlAssets**)`Bundle.main.url(forResource:"HtmlAssets",withExtension:nil)`. (4认同)
  • 版本1正在使用macOS上的WKWebView.虽然版本2不适用于macOS上的WKWebView.似乎allowReadAccessTo参数可能是解锁对macOS上的应用程序访问baseURL路径的关键. (3认同)

Mat*_*ift 11

Swift 4方法

此方法允许WKWebView正确读取链接的CSS/JS文件的目录和子目录的层次结构.你不是需要改变你的HTML,CSS和JS代码.

针对Xcode 9.3进行了更新

步骤1

将本地Web文件的文件夹导入到项目中的任何位置.确保你:

Xcode>文件>将文件添加到

☑️如果需要,复制项目

☑️ 创建文件夹引用 (不是"创建组")

☑️添加到目标

第2步

使用WKWebView转到View Controller并将以下代码添加到viewDidLoad方法中:

let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "website")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
Run Code Online (Sandbox Code Playgroud)
  • index- 要加载的文件的名称(不带.html扩展名)
  • website- 您的Web文件夹的名称(index.html应该位于此目录的根目录下)

结论

整体代码应如下所示:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView.uiDelegate = self
        webView.navigationDelegate = self

        let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "Website")!
        webView.loadFileURL(url, allowingReadAccessTo: url)
        let request = URLRequest(url: url)
        webView.load(request)
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您有任何关于此方法或代码的问题,我会尽力回答.:)

  • 如果你允许我,只需要一个简单的问题:为什么你以后使用`webView.loadFileURL`然后+`webView.load`?只是`loadFileURL`不起作用? (2认同)