В моем приложении 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, но это не помогло).
8 ответов
Это упрощенная версия того, что я использовал для загрузки локальных файлов в свой проект (iOS 10, Swift 3). Я только что обновил свой код (7.5.2017) после того, как снова протестировал его на iOS 10.3.1 и iPhone 7+ в соответствии с просьбой Рагурама и Fox5150 в комментариях.
Я только что создал совершенно новый проект, и это структура папок:
Обновление 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
}
}
На что следует обратить внимание:
- Убедитесь, что ваши локальные файлы 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">
Учитывая две версии и ошибки, вот мои файлы html / css из проекта:
Web / 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, сообщите мне в разделе комментариев, и я его загружу.
Swift 4 Метод
Этот метод позволяет WKWebView правильно читать вашу иерархию каталогов и подкаталогов для связанных файлов CSS / JS. Вам НЕ нужно менять код HTML, CSS или JS.
Обновлено для Xcode 9.3
Шаг 1
Импортируйте папку локальных веб-файлов в любое место вашего проекта. Убедитесь, что вы:
☑️ Копировать элементы при необходимости
Strong Создать ссылки на папки (не «Создавать группы»)
☑️ Добавить к целям
Шаг 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)
}
}
Если у кого-то из вас есть дополнительные вопросы об этом методе или коде, я постараюсь ответить. :)
Создание 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)
Проверьте этот билет: 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)
}
Это хорошо работает (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.")
}
}
}
}
Мне помогло это решение:
[configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
Это хорошо работает с URL-адресом файла или удаленным URL-адресом, а также независимо от того, находится ли файл в пакете или в документах:
if url.isFileURL {
webView.loadFileURL(url, allowingReadAccessTo: url)
} else {
let request = URLRequest(url: url)
webView.load(request)
}
Файлы должны находиться в каталоге документов.
Для получения документа я реализовал следующее:
let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileNameWithExtension = "IMG_0002.PNG"
let indexFileUrl = documentDirUrl.appendingPathComponent(fileNameWithExtension)
if FileManager.default.fileExists(atPath: indexFileUrl.path) {
webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)
}
Похожие вопросы
Связанные вопросы
Новые вопросы
ios
iOS - мобильная операционная система, работающая на Apple iPhone, iPod touch и iPad. Используйте этот тег [ios] для вопросов, связанных с программированием на платформе iOS. Используйте связанные теги [target-c] и [swift] для проблем, характерных для этих языков программирования.