WKWebView charge les ressources à partir du dossier de document local

dans mon application Swift iOS, je veux 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 quand je suis passé à de vrais téléphones, il a juste montré une page blanche. Je me suis alors connecté à L'application en utilisant Safari, et j'ai trouvé qu'il se plaignait avec "N'a pas réussi à charger la ressource".

j'ai alors essayé de lire d'abord le contenu de la page à htmlPath , puis utiliser

appWebView!.loadHTMLString()

pour charger la page. Cela fonctionne quand la page HTML est simple. Mais si le HTML renvoie à autre chose, c'est-à-dire à un fichier JavaScript également dans le répertoire des documents (avec un chemin absolu comme <script src="file:////var/mobile/Containers/Data/Application/762035C9-2BF2-4CDD-B5B1-574A0E2B0728/Documents/xxxxx.js"> ), il ne se chargera pas.

est-ce que quelqu'un sait pourquoi cela se produit, et comment résoudre le problème?

plus d'informations:

  • version XCode: 7.3.1
  • Cible de déploiement
  • : 8.1 (j'ai essayé d'utiliser 9.3 aussi, mais cela n'a pas aidé.)
21
demandé sur Darshan Rivka Whittle 2016-09-05 21:53:16

4 réponses

c'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 mis à 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 du dossier: enter image description here

Mise à jour le 19.04.2018: a ajouté une nouvelle fonctionnalité pour télécharger A.zip avec les fichiers HTML, CSS, JS, décompressez le dans /Documents/ (Alamofire + Zip) puis chargez ces fichiers dans le webView. Vous pouvez le trouver dans la GitHub exemple de projet . De nouveau, n'hésitez pas à fourche et l'étoile! :)

mise à jour 08.02.2018: a finalement ajouté un GitHub sample project , qui comprend également un fichier JavaScript local. Hésitez pas à la fourche et l'étoile! :)

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

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

Pièges à regarder dehors pour:

  • assurez-vous que vos fichiers html/js/css locaux sont dans le projet - > objectif -> phases de construction - > paquet de copie Ressources
  • assurez-vous que vos fichiers html ne font pas référence à des chemins relatifs par exemple css/styles.css parce que iOS aplatira la structure et les styles de vos fichiers.css sera au même niveau que l'indice.html écrire <link rel="stylesheet" type="text/css" href="styles.css"> à la place

étant donné les 2 versions et les gotchas 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 projet d'échantillon GitHub, dites-le moi dans la section des commentaires et je le téléchargerai.

27
répondu tech4242 2018-04-19 08:43:07

Méthode Swift 4

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 faites pas besoin de changer votre code HTML, CSS ou JS.

mise à jour pour Xcode 9.3

Étape 1

importer le dossier des fichiers Web locaux n'importe où dans votre projet. Assurez-vous que vous:

Xcode  File  Add Files to "Project"

envoyer les éléments de copie si nécessaire

☑️ Créer un dossier de références (pas de "Créer des groupes")

ajouter aux objectifs

l'Étape 2

aller au contrôleur de vue avec le WKWebView et ajouter le code suivant à la viewDidLoad méthode:

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)

Conclusion

le code général devrait ressembler à quelque chose comme 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 si vous avez des questions sur cette méthode ou sur le code, je ferai de mon mieux pour y répondre. :)

5
répondu Matt Swift 2018-04-03 19:32:36

Cette solution m'a aidé:

[configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
2
répondu Christian Anchor Dampf 2017-10-11 06:38:01

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.")
            }
        }
    }
}
0
répondu hkdalex 2017-06-24 13:52:07