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
WKWebView does load resources from local document folder
提问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:
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.css
because 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 文件的文件夹导入到您的项目中。确保您:
?? 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 viewDidLoad
method:
使用 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.html
extension)website
– the name of your web folder (index.html
should 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)
}