Dans mon application Swift iOS, je souhaite télécharger des pages HTML dynamiques à partir d'un serveur distant, les enregistrer dans le répertoire de documents et afficher ces pages à partir du répertoire de documents.
J'utilisais ceci pour charger la page:
var appWebView:WKWebView?
...
appWebView!.loadRequest(NSURLRequest(URL: NSURL(fileURLWithPath: htmlPath)))
Tout fonctionne sur le simulateur, mais lorsque je me suis installé sur de vrais téléphones, une page vierge s’est affichée. Je me suis ensuite connecté à l'application à l'aide de Safari et j'ai constaté qu'il se plaint de "Impossible de charger la ressource".
J'ai ensuite essayé de lire d'abord le contenu de la page à htmlPath
, puis d'utiliser
appWebView!.loadHTMLString()
charger la page. Cela fonctionne quand la page HTML est simple. Mais si le HTML fait référence à quelque chose d'autre, c'est-à-dire un fichier JavaScript également dans le répertoire du document (avec un chemin absolu comme <script src="file:////var/mobile/Containers/Data/Application/762035C9-2BF2-4CDD-B5B1-574A0E2B0728/Documents/xxxxx.js">
), le chargement échouera.
Quelqu'un sait-il pourquoi cela se produit et comment résoudre le problème?
Plus d'informations:
Ceci est une version simplifiée de ce que j'ai utilisé pour charger des fichiers locaux dans un de mes projets (iOS 10, Swift 3). Je viens de mettre à jour mon code (7.5.2017) après l'avoir testé à nouveau sur iOS 10.3.1 et iPhone 7+, comme demandé par Raghuram et Fox5150 dans les commentaires.
Je viens de créer un tout nouveau projet et voici la structure de dossiers:
Mise à jour 19.04.2018: Ajout d'une nouvelle fonctionnalité permettant de télécharger un fichier .Zip contenant des fichiers HTML, CSS, JS, de le décompresser dans/Documents/(Alamofire + Zip), puis de charger ces fichiers dans la WebView. Vous pouvez également le trouver dans le exemple de projet GitHub . Encore une fois, sentez-vous libre de fourchette et star! :)
Mise à jour 08.02.2018: a finalement ajouté un exemple de projet GitHub }, qui inclut également un fichier JavaScript local. Ne hésitez pas à fork et star! :)
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()
}
}
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()
}
}
Les pièges à surveiller:
css/styles.css
car iOS aplatira votre structure de fichier et styles.css sera au même niveau que index.html, écrivez donc <link rel="stylesheet" type="text/css" href="styles.css">
à la placeÉtant donné les 2 versions et les pièges, voici mes fichiers html/css du projet:
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>
web/css/styles.css
#webkit-h1 {
font-size: 80px;
color: lightblue;
}
Si quelqu'un veut un exemple de projet GitHub, dites-le-moi dans la section commentaires et je le téléchargerai.
Cette méthode permet à WKWebView de lire correctement votre hiérarchie de répertoires et de sous-répertoires pour les fichiers CSS/JS liés. Vous n'avez PAS besoin de changer votre code HTML, CSS ou JS.
Mis à jour pour Xcode 9.3
Importez le dossier des fichiers Web locaux n’importe où dans votre projet. Assurez-vous que vous:
☑️ Copier les éléments si nécessaire
☑️ Créer des références de dossier} _ (pas "Créer des groupes")
☑️ Ajouter aux cibles
Accédez au contrôleur de vue avec WKWebView et ajoutez le code suivant à la méthode 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
- le nom du fichier à charger (sans l'extension .html
)website
- le nom de votre dossier Web (index.html
devrait être à la racine de ce répertoire)Le code général devrait ressembler à ceci:
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)
}
}
Si l'un d'entre vous a d'autres questions sur cette méthode ou le code, je ferai de mon mieux pour y répondre. :)
Cette solution m'a aidé à:
[configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
Cela fonctionne bien (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.")
}
}
}
}
Cela fonctionne bien avec l'URL du fichier ou l'URL distante, et que le fichier soit dans l'ensemble ou dans les documents:
if url.isFileURL {
webView.loadFileURL(url, allowingReadAccessTo: url)
} else {
let request = URLRequest(url: url)
webView.load(request)
}