Charger les ressources à partir du chemin relatif à l'aide du code HTML local dans uiwebview


121

J'ai une application iOS très simple avec une uiwebview chargeant une page de test très simple (test.html):

<html>
<body>
<img src="img/myimage.png" />
</body>
</html>

Je charge ce fichier test.html dans ma vue Web:

NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSURL *baseUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
[webView loadHTMLString:html baseURL:baseUrl];

Cela fonctionne bien si je référence l'image sans le chemin relatif et que je mets l'image référencée dans le chemin racine sous Cibles -> Copier les ressources du bundle dans XCode, mais je ne peux pas le faire fonctionner avec le chemin relatif comme indiqué dans mon fichier html . Il doit y avoir un moyen de le faire, j'ai beaucoup d'images, de fichiers css, javascript que je veux charger dans la vue Web et je voudrais ne pas avoir tout à la racine et devoir changer toutes les références dans mon site Web app.

Réponses:


286

Voici comment charger / utiliser un html local avec des références relatives.

  1. Faites glisser la ressource dans votre projet xcode (j'ai fait glisser un dossier nommé www depuis ma fenêtre de recherche), vous obtiendrez deux options "créer des groupes pour tous les dossiers ajoutés" et "créer des références de dossiers pour tous les dossiers ajoutés".
  2. Sélectionnez l'option "créer des références de dossier ..".
  3. Utilisez le code ci-dessous. Cela devrait fonctionner comme un charme.

    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"]];
    [webview loadRequest:[NSURLRequest requestWithURL:url]];

Maintenant, tous vos liens relatifs (comme img / .gif, js / .js) dans le html devraient être résolus.

Swift 3

    if let path = Bundle.main.path(forResource: "dados", ofType: "html", inDirectory: "root") {
        webView.load( URLRequest(url: URL(fileURLWithPath: path)) )
    }

1
Super et Up ont voté! Quelqu'un peut-il expliquer pourquoi "créer des références de dossier par opposition à" créer des groupes pour tous les dossiers ajoutés "?
Sean

3
En passant, si vous essayez de charger des fichiers javascript plutôt que des images, vous devrez également regarder ceci: stackoverflow.com/a/3629479/385619
Willster

2
Que faire si le répertoire contient n dossiers? Est-il correct de passer une chaîne comme @"www/app"pour le répertoire arg?
ray

1
Et si nous chargeons le html à partir des documents, pas du bundle?
chipbk10

@Sean XCode stocke par défaut tous les fichiers ajoutés dans le dossier racine, les groupes ne servent qu'à donner une belle apparence à l'arborescence de votre projet. Les références de dossier copient en fait le contenu tel quel, en préservant la structure du répertoire. C'est assez essentiel si vous voulez que vos chemins relatifs fonctionnent sur l'appareil de la même manière qu'ils le font sur votre ordinateur de bureau.
Combuster

24

Dans Swift:

 func pathForResource(  name: String?, 
                        ofType ext: String?, 
                        inDirectory subpath: String?) -> String?  {

  // **name:** Name of Hmtl
  // **ofType ext:** extension for type of file. In this case "html"
  // **inDirectory subpath:** the folder where are the file. 
  //    In this case the file is in root folder

    let path = NSBundle.mainBundle().pathForResource(             "dados",
                                                     ofType:      "html", 
                                                     inDirectory: "root")
    var requestURL = NSURL(string:path!)
    var request = NSURLRequest(URL:requestURL)

    webView.loadRequest(request)
}

Merci pour le code Swift. A bien fonctionné avec la réponse acceptée
Bala Vishnu

Bienvenue! :.) @Bala Vishnu
Weles

Fonctionne très bien, j'ai dû le déballer requestURL.
RRikesh

5

J'ai tout entassé dans une seule ligne (mauvais je sais) et je n'ai eu aucun problème avec cela:

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" 
                                                                                                         ofType:@"html"]
                                                             isDirectory:NO]]];         

1
Dans le projet XCode de votre image sous le nœud des cibles, utilisez-vous "Relative to project" ou "Relative to Enclosing Group"? J'utilisais Relatif au projet car dans la boîte de dialogue Obtenir des informations, le chemin indiqué lorsque je choisis Relatif au projet semble correct. Cependant, il semble charger l'image correctement lorsque je choisis par rapport au groupe englobant. Maintenant, je viens de faire fonctionner ma page complète correctement avec javascript et css et tout, merci!
Matt Palmerlee

Pouah! Cette uiwebview est si fragile, j'ai commencé à ajouter lentement des tests plus complexes à ma page de test (c'est-à-dire en définissant l'image avec css au lieu de l'inline dans la balise img) et cela ne fonctionnait pas alors je suis revenu à ce que j'avais à l'origine et cela n'a pas fonctionné ne travaille plus! Peut-être ai-je affaire à une sorte de mise en cache dans mon uiwebview?
Matt Palmerlee

5

Je fais simplement ceci:

    UIWebView *webView = [[[UIWebView alloc] init] autorelease];

    NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];

Où "index.html" fait référence relativement aux images, CSS, javascript, etc.


2

Réponse rapide 2.

La référence de classe UIWebView déconseille d'utiliser webView.loadRequest (request):

N'utilisez pas cette méthode pour charger des fichiers HTML locaux; à la place, utilisez loadHTMLString: baseURL :.

Dans cette solution, le code HTML est lu dans une chaîne. L'URL du html est utilisée pour déterminer le chemin et le transmet comme URL de base.

let url = bundle.URLForResource("index", withExtension: "html", subdirectory: "htmlFileFolder")
let html = try String(contentsOfURL: url)
let base = url.URLByDeletingLastPathComponent
webView.loadHTMLString(html, baseURL: base)

Si tel est le cas, il serait bon de se référer à l'endroit où dans le manuel il le conseille et d'insérer un extrait de cette page - cela semble vraiment sans contexte pour le moment.
Ben Cox

Le commentaire d'Apple est sur la page Méthode d'instance pour loadRequest:
Jeff

0

Je suis retourné et testé et re-testé cela, il semble que la seule façon de le faire fonctionner (puisque j'ai des fichiers dans le dossier img et d'autres dans js / css, etc ...) n'est pas de utilisez un chemin relatif vers mon image dans le html et faites référencer tout dans le dossier du bundle. C'est dommage :(.

<img src="myimage.png" />

0

Réponse de @ sdbrain dans Swift 3:

    let url = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")!)
    webView.loadRequest(NSURLRequest.init(url: url) as URLRequest)

-1

Dans Swift 3.01 en utilisant WKWebView:

let localURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "CWP")!)
myWebView.load(NSURLRequest.init(url: localURL) as URLRequest)

Cela ajuste certaines des modifications de syntaxe les plus fines de la version 3.01 et maintient la structure des répertoires en place afin que vous puissiez incorporer les fichiers HTML associés.


Le préfixe NS n'a-t-il pas été supprimé pour les principaux types de fondation depuis 3.x? Cela a fait l'affaire pour moi, merci! let localURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "mapa_procesos")!) webView.loadRequest(URLRequest(url: localURL))
Eduardo Gomez
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.