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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39336235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:03:38  来源:igfitidea点击:

WKWebView does load resources from local document folder

iosswiftwkwebview

提问by Peter

In my Swift iOS app, I want to download some dynamic HTML pages from a remote server, save them in the document directory, and display those pages from document directory.

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

I was using this to load the page:

我正在使用它来加载页面:

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

Everything works on the simulator, but when I moved to real phones, it just showed a blank page. I then connected to the app using Safari, and found it complained with "Failed to load resource".

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

I then tried to first read the content of the page at htmlPath, then use

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

appWebView!.loadHTMLString()

to load the page. It works when the HTML page is simple. But if the HTML references something else, i.e. a JavaScript file also in the document directory (with an absolute path like <script src="file:////var/mobile/Containers/Data/Application/762035C9-2BF2-4CDD-B5B1-574A0E2B0728/Documents/xxxxx.js">), it will fail to load.

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

Does anyone know why this happens, and how to resolve the issue?

有谁知道为什么会发生这种情况,以及如何解决这个问题?

More info:

更多信息:

  • XCode version: 7.3.1
  • Deployment Target: 8.1 (I tried to use 9.3 too, but that didn't help.)
  • XCode 版本:7.3.1
  • 部署目标:8.1(我也尝试使用 9.3,但这没有帮助。)

采纳答案by tech4242

This is a simplified version of what I have used to load local files in a project of mine (iOS 10, Swift 3). I have just updated my code (7.5.2017)after testing it out again on iOS 10.3.1 and iPhone 7+ as requested by Raghuram and Fox5150 in the comments.

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

I just created a completely new project and this is the folder structure:enter image description here

我刚刚创建了一个全新的项目,这是文件夹结构:在此处输入图片说明

Update 19.04.2018:Added a new feature to download a .zip with HTML, CSS, JS files, unzip it in /Documents/ (Alamofire + Zip) and then load those files into the webView. You can find it in the GitHub sample projectas well. Again, feel free to fork & star! :)

2018 年 4 月 19 日更新:添加了一项新功能,可以下载包含 HTML、CSS、JS 文件的 .zip,将其解压缩到 /Documents/ (Alamofire + Zip) 中,然后将这些文件加载​​到 webView 中。您也可以在GitHub 示例项目中找到它。再次,随意分叉和星标!:)

Update 08.02.2018:finally added a GitHub sample project, which also includes a local JavaScript file. Feel free to fork & star! :)

2018 年 2 月 8 日更新:终于添加了一个GitHub 示例项目,其中还包含一个本地 JavaScript 文件。随意分叉和星标!:)

Version 1 with webView.loadFileURL()

带有 webView.loadFileURL() 的版本 1

ViewController.swift

视图控制器.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
    }
}

Version 2 with webView.loadHTMLString()

带有 webView.loadHTMLString() 的版本 2

ViewController.swift

视图控制器.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
    }
}

Gotchas to look out for:

需要注意的问题:

  • Make sure that your local html/js/css files are in Project -> Target -> Build Phases -> Copy Bundle Resources
  • Make sure that your html files don't reference relative paths e.g. css/styles.cssbecause iOS will flatten your file structure and styles.css will be on the same level as index.html so write <link rel="stylesheet" type="text/css" href="styles.css">instead
  • 确保您的本地 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">,而不是

Given the 2 versions and the gotchas here are my html/css files from the project:

鉴于 2 个版本和这里的问题是我来自项目的 html/css 文件:

web/index.html

网页/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>

web/css/styles.css

网页/CSS/styles.css

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

If somebody wants a GitHub sample project, tell me in the comments section and I'll upload it.

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

回答by Matt Swift

Swift 4 Method

Swift 4 方法

This method allows WKWebView to properly read your hierarchy of directories and sub-directories for linked CSS/JS files. You do NOTneed to change your HTML, CSS or JS code.

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

Updated for Xcode 9.3

为 Xcode 9.3 更新

Step 1

第1步

Import the folder of local web files anywhere into your project. Make sure that you:

将本地 Web 文件的文件夹导入到您的项目中。确保您:

Xcode >File >Add Files to "Project"

Xcode >文件 >将文件添加到“项目”

?? Copy items if needed

?? Create folder references(not "Create groups")

?? Add to targets

?? 如果需要,复制项目

?? 创建文件夹引用(不是“创建组”)

?? 添加到目标

Step 2

第2步

Go to the View Controller with the WKWebView and add the following code to the viewDidLoadmethod:

使用 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)
  • index– the name of the file to load (without the .htmlextension)
  • website– the name of your web folder (index.htmlshould be at the root of this directory)
  • index– 要加载的文件的名称(不带.html扩展名)
  • website– 您的 Web 文件夹的名称(index.html应位于此目录的根目录)

Conclusion

结论

The overall code should look something like this:

整体代码应如下所示:

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)
    }

}

If any of you have further questions about this method or the code, I'll do my best to answer. :)

如果你们对这个方法或代码有进一步的问题,我会尽力回答。:)

回答by Christian Anchor Dampf

This solution helped me:

这个解决方案帮助了我:

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

回答by drewster

This works nicely with file URL or remote URL, and whether file is in the bundle or in documents:

这适用于文件 URL 或远程 URL,以及文件是在包中还是在文档中:

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

回答by hkdalex

This works well (Swift 3, Xcode 8):

这很有效(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.")
            }
        }
    }
}

回答by hgwhittle

Constructing the URLs this way allowed me to load resources from the document directory with WKWebView:

以这种方式构建 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)

回答by ΩlostA

Check that ticket: iOS: How to load local files (not in the bundle) in a WKWebView?

检查该票证:iOS:如何在 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)
}