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

时间:2016-09-05 18:53:17

标签: ios swift wkwebview

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

我用它来加载页面:

var appWebView:WKWebView?
...
appWebView!.loadRequest(NSURLRequest(URL: NSURL(fileURLWithPath: htmlPath)))

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

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

appWebView!.loadHTMLString()

加载页面。它在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,但这没有帮助。)

8 个答案:

答案 0 :(得分:32)

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

我刚创建了一个全新的项目,这是文件夹结构:enter image description here

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

更新08.02.2018:最后添加了GitHub sample project,其中还包含本地JavaScript文件。随意分叉&amp;星! :)

带有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
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

版本2,包含webView.loadHTMLString()

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
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

需要注意:

  • 确保您的本地html / js / css文件位于Project - &gt;目标 - &gt;构建阶段 - &gt;复制捆绑资源
  • 确保您的html文件不引用相对路径,例如css/styles.css因为iOS会压缩你的文件结构,而style.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>

网/ CSS / styles.css的

#webkit-h1 {
  font-size: 80px;
  color: lightblue;
}

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

答案 1 :(得分:7)

Swift 4方法

此方法允许WKWebView正确读取链接的CSS / JS文件的目录和子目录的层次结构。您 NOT 需要更改HTML,CSS或JS代码。

针对Xcode 9.3进行了更新

第1步

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

Xcode > File > Add Files to "Project"

  

☑️根据需要复制项目

     

☑️创建文件夹引用 (不是“创建群组”)

     

☑️添加到目标

第2步

使用WKWebView转到View Controller,并将以下代码添加到matvec(J) += value(p,q) * x(I)方法中:

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) - 要加载的文件的名称(不含index扩展名)
  • .html - 您的网络文件夹的名称(website应位于此目录的根目录)

结论

整体代码应如下所示:

index.html

如果您对此方法或代码有任何疑问,我会尽力回答。 :)

答案 2 :(得分:2)

这个解决方案帮助了我:

[configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];

答案 3 :(得分:1)

这很有效(Swift 3,Xcode 8):

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    var webView: WKWebView!

    override func loadView() {
        webView = WKWebView()
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        if let url = Bundle.main.url(forResource: "file", withExtension: "txt")
        {
            do
            {
                let contents = try String(contentsOfFile: url.path)
                webView.loadHTMLString(contents, baseURL: url.deletingLastPathComponent())
            }
            catch
            {
                print("Could not load the HTML string.")
            }
        }
    }
}

答案 4 :(得分:1)

以这种方式构造URL允许我使用WKWebView从文档目录中加载资源:

guard let docDir = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) else {
    return
}

let resourceURL = docDir.appendingPathComponent("/Path/To/Your/Resource")
self.wkWebView.loadFileURL(resourceURL, allowingReadAccessTo: docDir)

答案 5 :(得分:0)

这可以很好地与文件URL或远程URL配合使用,无论文件是在分发包中还是在文档中:

if url.isFileURL {
    webView.loadFileURL(url, allowingReadAccessTo: url)
} else {
    let request = URLRequest(url: url)
    webView.load(request)
}

答案 6 :(得分:0)

文件必须在文档目录中。

我实现了以下操作来检索文档:

let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileNameWithExtension = "IMG_0002.PNG"
let indexFileUrl = documentDirUrl.appendingPathComponent(fileNameWithExtension)
if FileManager.default.fileExists(atPath: indexFileUrl.path) {
    webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)
}

答案 7 :(得分:-1)

检查该票证:iOS: How to load local files (not in the bundle) in a WKWebView?

var nsurl = URL(fileURLWithPath: URL(fileURLWithPath: URL(fileURLWithPath: documentsDirectory()).appendingPathComponent(user_appli).absoluteString).appendingPathComponent("index.html").absoluteString) //locally
var readAccessToURL: URL? = nsurl.deletingLastPathComponent?.deletingLastPathComponent

if let anURL = readAccessToURL {
    webView?.loadFileURL(nsurl, allowingReadAccessTo: anURL)
}
相关问题