首页 文章

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

提问于
浏览
23

在我的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,但这没有帮助 . )

5 回答

  • 6

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

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

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

    Update 08.02.2018: 最后添加了一个GitHub sample project,其中还包含一个本地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
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    

    带有webView.loadHTMLString()的

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

    Gotchas to look out for:

    • 确保您的本地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:

    网络/ 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示例项目,请在评论部分告诉我,我会上传它 .

  • 2

    Swift 4方法

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

    针对Xcode 9.3进行了更新

    第1步

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

    Xcode > File > Add Files to "Project"

    ☑️根据需要复制项目☑️创建文件夹参考(不是“创建组”)☑️添加到目标

    第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)
    
    • index - 要加载的文件的名称(不带 .html 扩展名)

    • website - 您的网络文件夹的名称( 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)
        }
    
    }
    

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

  • 0

    这个解决方案帮助我:

    [configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
    
  • -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.")
                }
            }
        }
    }
    
  • 27

    检查那张票: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)
    }
    

相关问题