Подтвердить что ты не робот

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, но это не помогло.)
4b9b3361

Ответ 1

Это упрощенная версия того, что я использовал для загрузки локальных файлов в моем проекте (iOS 10, Swift 3). Я только что обновил свой код (7.5.2017) после его повторного тестирования на iOS 10.3.1 и iPhone 7+ в соответствии с просьбами Рагурама и Fox5150 в комментариях.

Я только что создал совершенно новый проект, и это структура папок:enter image description here

Обновление 19.04.2018: Добавлена новая функция для загрузки .zip с файлами HTML, CSS, JS, разархивируйте его в /Documents/(Alamofire + Zip) и затем загрузите эти файлы в webView. Вы также можете найти его в примере проекта GitHub. Опять же, не стесняйтесь вилка & звезда! :)

Обновление 08.02.2018: наконец-то добавил пример проекта GitHub, который также включает локальный файл JavaScript. Не стесняйтесь раскошелиться звезда! :)

Версия 1 с webView.loadFileURL()

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

Версия 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
    }
}

Gotchas, чтобы высматривать:

  • Убедитесь, что ваши локальные html/js/css файлы находятся в Project → Target → Build Phase → Copy Bundle Resources
  • Убедитесь, что ваши HTML файлы не ссылаются на относительные пути, например css/styles.css, потому что iOS сгладит вашу файловую структуру, а styles.css будет на том же уровне, что и index.html, поэтому вместо этого напишите <link rel="stylesheet" type="text/css" href="styles.css">

Учитывая 2 версии и ошибки, вот мои 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, сообщите мне об этом в разделе комментариев, и я его выложу.

Ответ 2

Свифт 4 Метод

Этот метод позволяет WKWebView правильно читать иерархию каталогов и подкаталогов для связанных файлов CSS/JS. Вам НЕ нужно менять код HTML, CSS или JS.

Обновлено для Xcode 9.3

Шаг 1

Импортируйте папку локальных веб файлов в любое место вашего проекта. Убедитесь, что вы:

Xcode > File > Add Files to "Project"

☑️ Копировать элементы при необходимости

☑️ Создавать ссылки на папки (не "Создавать группы")

☑️ Добавить к целям

Шаг 2

Перейдите в View Controller с помощью WKWebView и добавьте следующий код в метод 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)
    }

}

Если у кого-то из вас возникнут дополнительные вопросы об этом методе или коде, я постараюсь ответить. :)

Ответ 3

Это решение помогло мне:

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

Ответ 4

Это хорошо работает (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.")
            }
        }
    }
}

Ответ 5

Это хорошо работает с URL-адресом файла или удаленным URL-адресом, а также с тем, находится ли файл в комплекте или в документах:

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

Ответ 6

Проверьте этот тикет: 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)
}