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.

Matt Palmerlee
la source

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)) )
    }
sdbrain
la source
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)
}
Weles
la source
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]]];         
PengOne
la source
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.

Vieux McStopher
la source
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)
Ce n'est pas moi
la source
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" />
Matt Palmerlee
la source
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)
Skornos
la source
-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.

Bobo courbé
la source
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