Загрузка локальных веб файлов и ресурсов в WKWebView

В отличие от UIWebView и предыдущих версий WKWebView (iOS 10 и macOS 10.12), операция загрузки по умолчанию для локальных файлов переместилась с Bundle.main.path на Bundle.main.url. Аналогично, loadFileURL также стал функцией по умолчанию для загрузки локальных ресурсов в WKWebView.

Я знаю, что .path и .url совершенно разные и оба работали в прошлом - .path исторически был выбранным по умолчанию способом; однако, кажется, что последние версии Swift нарушили большинство, если не всех, решений .path. .path похоже, теперь сглаживают иерархию каталогов, помещая все CSS, JS и любые другие содержимое подкаталогов в один большой каталог. Это вызывает ошибки при загрузке, когда WKWebView пытается загрузить index.html, например, со связанной /css/style.css стилей /css/style.css (например, /css/style.css).

Увидев многочисленные вопросы и бесчисленные неопределенные/сломанные ответы на совпадение, есть ли быстрое и безболезненное решение для реализации WKWebView, которое может загружать локальные ресурсы (включая связанные файлы CSS/JS) без каких-либо обходных решений?

Ответ 1

Обновлено для Swift 4, Xcode 9.3


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

Решение (Быстрое)

  1. Добавьте веб-папку в ваш проект (Файл> Добавить файлы в проект)
    • Копировать элементы, если это необходимо
    • Создать ссылки на папки *
    • Добавить к целям (которые применимы)
  2. Добавьте следующий код в 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)
    

Решение (углубленное)

Шаг 1

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

Xcode > File > Add Files to "Project"

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

☑️ Create folder references (not "Create groups")

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

Шаг 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)
    }

}

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

Ответ 2

Эта работа для меня:

        WKWebView *wkwebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
        wkwebView.navigationDelegate = self;
        wkwebView.UIDelegate = self;
        [wkwebView.configuration.preferences setValue:@"TRUE" forKey:@"allowFileAccessFromFileURLs"];
        NSURL *url = [NSURL fileURLWithPath:YOURFILEPATH];
        [wkwebView loadFileURL:url allowingReadAccessToURL:url.URLByDeletingLastPathComponent];
        [self.view addSubview:wkwebView];