Utilisation du HTML et des images locales dans UIWebView

164

J'ai un UIWebView dans mon application que je souhaite utiliser pour afficher une image qui sera liée à une autre URL.

j'utilise

<img src="image.jpg" /> to load the image.

Le problème est que l'image ne se charge pas (c'est-à-dire qu'elle ne peut pas être trouvée) même si elle est ajoutée en tant que ressource dans mon projet et copiée dans le bundle.

J'ai essayé d'utiliser NSBundle pour obtenir le chemin complet de l'image et de l'utiliser et cela n'apparaît toujours pas dans la vue Web.

Des idées?

Jasarien
la source
Je ne suis plus en mesure de le faire à partir de l'iPhone OS 3.0. :( Plus d'infos (StackOverflow.com).
Joe D'Andrea
8
Pourquoi voter contre? : /
Jasarien
5
Ce n'est pas nécessairement qu'ils sont mauvais. Peut-être avaient-ils une raison légitime? Nous ne saurons probablement jamais. Si seulement ils avaient la courtoisie d'expliquer pourquoi ils ont voté contre dans un commentaire ...
Jasarien
63
Il devrait être obligatoire d'écrire un commentaire sur un vote contre.
Robert
@Jasarien: J'ai besoin des mêmes fonctionnalités. mais je ne comprends pas ce qui doit être passé dans htmlString dans [webView loadHTMLString: htmlString baseURL: baseURL] et comment je mets <img src = "image.jpg" /> mon image en html.
iPhone

Réponses:

291

Utilisation de chemins ou de fichiers relatifs: les chemins pour faire référence aux images ne fonctionnent pas avec UIWebView. Au lieu de cela, vous devez charger le HTML dans la vue avec la baseURL correcte:

NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webView loadHTMLString:htmlString baseURL:baseURL];

Vous pouvez alors vous référer à vos images comme ceci:

<img src="myimage.png">

(de uiwebview revisité )

Adam Alexander
la source
15
[[NSBundle mainBundle] bundleURL] nous pouvons l'utiliser comme bundleURL
Naveen Shan
2
Tout ce que cela fait pour moi est de me donner une chaîne dans ma vue Web que j'ai définie pour mon htmlString. c'est-à-dire que tout ce qu'il montre sur la page est "tour.html"
Chewie The Chorkie
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
dans le cas de Xamarin ad MonoTouch webvie.LoadHtmlString (strig, NSBundle.MainBundle.BundleUrl);
Erik Simonic
1
Fonctionne parfaitement dans le simulateur, mais pas sur mon appareil
jose920405
46

Utilisez ceci:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
TV Lithu
la source
5
Mais votre réponse est identique à la réponse postée il y a 3 ans ... Votre réponse n'offre rien de différent, elle n'avait pas besoin d'être postée car la réponse acceptée couvrait déjà ce que vous avez posté.
Jasarien
13
C'est une version pratique en une ligne de la réponse acceptée - pas de mal à l'avoir ici.
MusiGenesis
9
@Jasarien cette réponse d'Adam Alexander était la seule solution jusqu'en août 2009. Mais à partir de la version 10.6 de Max OS X, cette nouvelle propriété a bundleURLété ajoutée dans NSBundle. Pas besoin de prendre bundlePath et de le convertir en URL. Donc, pour les personnes travaillant dans des versions supérieures à 10.6, cela donne une meilleure solution.
rineez
vu beaucoup de -ve activités dans ce post récemment .. Et personne n'a noté pourquoi?
Lithu TV
24

Je viens de rencontrer ce problème aussi. Dans mon cas, je traitais de certaines images qui n'étaient pas localisées et d'autres qui l'étaient - en plusieurs langues. Une URL de base n'a pas obtenu les images dans des dossiers localisés pour moi. J'ai résolu ce problème en procédant comme suit:

// make sure you have the image name and extension (for demo purposes, I'm using "myImage" and "png" for the file "myImage.png", which may or may not be localized)
NSString *imageFileName = @"myImage";
NSString *imageFileExtension = @"png";

// load the path of the image in the main bundle (this gets the full local path to the image you need, including if it is localized and if you have a @2x version)
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageFileName ofType:imageFileExtension];

// generate the html tag for the image (don't forget to use file:// for local paths)
NSString *imgHTMLTag = [NSString stringWithFormat:@"<img src=\"file://%@\" />", imagePath];

Ensuite, utilisez imgHTMLTag dans votre code HTML UIWebView lorsque vous chargez le contenu.

J'espère que cela aidera quiconque a rencontré le même problème.

Anton
la source
1
L'utilisation file://était ce dont j'avais besoin.
So Over It
Bien
8

essayez d'utiliser la chaîne d'image base64.

NSData* data = UIImageJPEGRepresentation(image, 1.0f);

NSString *strEncoded = [data base64Encoding];   

<img src='data:image/png;base64,%@ '/>,strEncoded
Ping
la source
6

J'ai eu un problème similaire, mais toutes les suggestions n'ont pas aidé.

Cependant, le problème était le * .png lui-même. Il n'avait pas de canal alpha . D'une manière ou d'une autre, Xcode ignore tous les fichiers png sans canal alpha pendant le processus de déploiement.


la source
Qu'est-ce que vous avez fait pour en sortir? Avez-vous trouvé une solution? Je suis confronté au même problème. UIWebView n'affiche pas les images car il n'a pas de canal alpha.
spaleja
1
J'ai utilisé Gimp pour ajouter un canal alpha à mes fichiers png. Voir docs.gimp.org/en/gimp-layer-alpha-add.html
3

Vous pouvez ajouter un dossier (disons WEB avec des sous-dossiers css, img et js et fichier test.html) à votre projet en choisissant Ajouter des fichiers à "MyProj" et en sélectionnant Créer des références de dossier . Maintenant, le code suivant s'occupera de toutes les images référencées, css et javascript

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WEB/test.html" ofType:nil];
[webView  loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
Zeeawan
la source
3

Dans Swift 3:

webView.loadHTMLString("<img src=\"myImg.jpg\">", baseURL: Bundle.main.bundleURL)

Cela a fonctionné pour moi même lorsque l'image était à l'intérieur d'un dossier sans aucune modification.

MrAn3
la source
2

Après avoir lu quelques chapitres dans le Cookbok de programmation iOS 6 et commencé à apprendre la programmation objective-c et iOS, je voudrais simplement ajouter que si l'on veut charger des ressources à partir d'un bundle personnalisé et l'utiliser dans une vue Web , cela peut être accompli comme ceci:

NSString *resourcesBundlePath = [[NSBundle mainBundle] pathForResource:@"Resources" ofType:@"bundle"];
NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcesBundlePath];
[self.outletWebView loadHTMLString:[html description] baseURL:[resourcesBundle bundleURL]];

Ensuite, dans votre html, vous pouvez faire référence à une ressource en utilisant le bundle "personnalisé" comme chemin de base:

body {
    background-image:url('img/myBg.png');
}
Lasse Christiansen
la source
1

Version Swift de la réponse de Lithu TV:

webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)
Musa almatri
la source
1

La version Swift d'Adam Alexanders Objective C répond:

let logoImageURL = NSURL(fileURLWithPath: "\(Bundle.main.bundlePath)/PDF_HeaderImage.png")
RJH
la source
0

Si vous utilisez des liens relatifs vers des images, les images ne s'afficheront pas car toutes les structures de dossiers ne sont pas conservées après la compilation de l'application iOS. Ce que vous pouvez faire est de convertir votre dossier Web local en un ensemble en ajoutant l' extension de nom de fichier « .bundle ».

Donc, si votre site Web local est contenu dans un dossier « www », celui-ci doit être renommé « www.bundle ». Cela permet de conserver les dossiers d'images et la structure des répertoires. Chargez ensuite le fichier ' index.html ' dans la WebView sous forme de chaîne HTML avec ' baseURL ' (défini sur www.bundle path) pour activer le chargement des liens relatifs aux images.

NSString *mainBundlePath = [[NSBundle mainBundle] resourcePath];
NSString *wwwBundlePath = [mainBundlePath stringByAppendingPathComponent:@"www.bundle"];
NSBundle *wwwBundle = [NSBundle bundleWithPath:wwwBundlePath];
if (wwwBundle != nil) {
    NSURL *baseURL = [NSURL fileURLWithPath:[wwwBundle bundlePath]];
    NSError *error = nil;
    NSString *page = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];
    NSString *pageSource = [NSString stringWithContentsOfFile:page encoding:NSUTF8StringEncoding error:&error];
    [self.webView loadHTMLString:pageSource baseURL:baseURL];
}
David Douglas
la source
0

Ces réponses m'ont aidé - en particulier le fichier: \\ xxxxxxx.xxx, mais j'ai dû faire une solution de contournement pour afficher l'image.

Dans mon cas, j'ai un fichier HTML sur mon serveur que je télécharge dans le répertoire des documents. Je veux l'afficher avec un graphique local dans un UIWebView que je n'ai pas pu obtenir pour travailler. Voici ce que j'ai fait:

  1. Copiez le fichier du NSBundle dans le répertoire de documents local
  2. Référencez le fichier dans mon document HTML en tant que "fichier: \\ filename.png"

Donc, au démarrage, copiez le fichier dans le répertoire des documents:

-(BOOL)copyBundleFilesToDocumentsDirectoryForFileName:(NSString *)fileNameToCopy OverwriteExisting:(BOOL)overwrite {
        //GET DOCUMENTS DIR
        //Search for standard documents using NSSearchPathForDirectoriesInDomains
        //First Param = Searching the documents directory
        //Second Param = Searching the Users directory and not the System
        //Expand any tildes and identify home directories.
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDir = [paths objectAtIndex:0];

        //COPY FILE FROM NSBUNDLE File to Local Documents Dir
        NSString *writableFilePath = [documentsDir  stringByAppendingPathComponent:fileNameToCopy];

        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSError *fileError;

        DDLogVerbose(@"File Copy From Bundle to Documents Dir would go to this path: %@", writableFilePath);

        if ([fileManager fileExistsAtPath:writableFilePath]) {
            DDLogVerbose(@"File %@ already exists in Documents Dir", fileNameToCopy);

            if (overwrite) {
                [fileManager removeItemAtPath:writableFilePath error:nil];
                DDLogVerbose(@"OLD File %@ was Deleted from  Documents Dir Successfully", fileNameToCopy);
            } else {
                return (NO);
            }
        }

        NSArray *fileNameParts = [fileNameToCopy componentsSeparatedByString:@"."];
        NSString *bundlePath = [[NSBundle mainBundle]pathForResource:[fileNameParts objectAtIndex:0] ofType:[fileNameParts objectAtIndex:1]];
        BOOL success = [fileManager copyItemAtPath:bundlePath toPath:writableFilePath error:&fileError];

        if (success) {
            DDLogVerbose(@"Copied %@ from Bundle to Documents Dir Successfully", fileNameToCopy);
        } else {
            DDLogError(@"File %@ could NOT be copied from bundle to Documents Dir due to error %@!!", fileNameToCopy, fileError);
        }

    return (success);
}
DocteurG
la source
-7

Ma solution complexe (ou tutoriel) pour rss-feed (get in RSSItems) ne fonctionne que sur l'appareil:

#define CACHE_DIR       [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]

for (RSSItem *item in _dataSource) {

    url = [NSURL URLWithString:[item link]];
    request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];

    [NSURLConnection sendAsynchronousRequest:request
                                       queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

                               @autoreleasepool {

                                   if (!error) {

                                       NSString *html = [[NSString alloc] initWithData:data
                                                                              encoding:NSWindowsCP1251StringEncoding];

                                       {
                                           NSError *error = nil;

                                           HTMLParser *parser = [[HTMLParser alloc] initWithString:html error:&error];

                                           if (error) {
                                               NSLog(@"Error: %@", error);
                                               return;
                                           }

                                           HTMLNode *bodyNode = [parser body];

                                           NSArray *spanNodes = [bodyNode findChildTags:@"div"];

                                           for (HTMLNode *spanNode in spanNodes) {
                                               if ([[spanNode getAttributeNamed:@"class"] isEqualToString:@"page"]) {

                                                   NSString *absStr = [[response URL] absoluteString];
                                                   for (RSSItem *anItem in _dataSource)
                                                       if ([absStr isEqualToString:[anItem link]]){

                                                           NSArray *spanNodes = [bodyNode findChildTags:@"img"];
                                                           for (HTMLNode *spanNode in spanNodes){
                                                               NSString *imgUrl = [spanNode getAttributeNamed:@"src"];
                                                               if (imgUrl){
                                                                   [anItem setImage:imgUrl];
                                                                   break;
                                                               }
                                                           }

                                                           [anItem setHtml:[spanNode rawContents]];
                                                           [self subProcessRSSItem:anItem];
                                                       }
                                               }
                                           }

                                           [parser release];
                                       }

                                       if (error) {
                                           NSLog(@"Error: %@", error);
                                           return;
                                       }

                                       [[NSNotificationCenter defaultCenter] postNotificationName:notification_updateDatasource
                                                                                           object:self
                                                                                         userInfo:nil];

                                   }else
                                       NSLog(@"Error",[error userInfo]);
                               }
                           }];

et

- (void)subProcessRSSItem:(RSSItem*)item{

NSString *html = [item html];
if (html) {

    html = [html stringByReplacingOccurrencesOfString:@"<div class=\"clear\"></div>"
                                           withString:@""];

    html = [html stringByReplacingOccurrencesOfString:@"<p class=\"link\">"
                                           withString:@""];

    html = [html stringByReplacingOccurrencesOfString:@"<div class=\"page\">"
                                           withString:@""];

    html = [html stringByReplacingOccurrencesOfString:@"</div>"
                                           withString:@""];

    NSArray *array1 = [html componentsSeparatedByString:@"<a"];
    if ([array1 count]==2) {
        NSArray *array2 = [html componentsSeparatedByString:@"a>"];

        html = [[array1 objectAtIndex:0] stringByAppendingString:[array2 objectAtIndex:1]];
    }

    NSURL *url;
    NSString *fileName;
    NSString *filePath;
    BOOL success;
    if ([item image]) {

        url = [NSURL URLWithString:
                      [hostString stringByAppendingString:[item image]]];
        NSData *imageData = [NSData dataWithContentsOfURL:url];

        fileName = [[[url relativePath] componentsSeparatedByString:@"/"] lastObject];

        filePath = [NSString stringWithFormat:@"%@/%@",
                              CACHE_DIR,
                              fileName];

        //save image locally
        success = [[NSFileManager defaultManager] createFileAtPath:filePath
                                                               contents:imageData
                                                             attributes:nil];

        //replace links
        html = [html stringByReplacingOccurrencesOfString:[item image]
                                               withString:filePath];

        [item setImage:fileName];

        //Передадим обновление интерфейса, снабдив индексом обновляемой ячейки
        [[NSNotificationCenter defaultCenter] postNotificationName:notification_updateRow
                                                            object:self
                                                          userInfo:[NSDictionary dictionaryWithObject:@([_dataSource indexOfObject:item])
                                                                                               forKey:@"row"]];
    }

    //finalize html
    html = [NSString stringWithFormat:@"<html><body>%@</body></html>",html];

    fileName = [[[item link] componentsSeparatedByString:@"/"] lastObject];
    filePath = [NSString stringWithFormat:@"%@/%@",
                CACHE_DIR,
                fileName];
    success = [[NSFileManager defaultManager] createFileAtPath:filePath
                                                      contents:[html dataUsingEncoding:NSUTF8StringEncoding]
                                                    attributes:nil];

    [item setHtml:
     (success)?filePath:nil];//for direct download in other case
}

}

sur le contrôleur de vue

- (void)viewDidAppear:(BOOL)animated{

RSSItem *item = [[DataSingleton sharedSingleton] selectedRSSItem];

NSString* htmlString = [NSString stringWithContentsOfFile:[item html]
                                                 encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL URLWithString:CACHE_DIR];

[_webView loadHTMLString:htmlString
                 baseURL:baseURL];

}

classe d'élément rss

#import <Foundation/Foundation.h>

@interface RSSItem : NSObject

@property(nonatomic,retain) NSString *title;
@property(nonatomic,retain) NSString *link;
@property(nonatomic,retain) NSString *guid;
@property(nonatomic,retain) NSString *category;
@property(nonatomic,retain) NSString *description;
@property(nonatomic,retain) NSString *pubDate;
@property(nonatomic,retain) NSString *html;
@property(nonatomic,retain) NSString *image;
@end

partie de n'importe quel html avec image

<html><body>
<h2>blah-blahTC One Tab 7</h2>
<p>blah-blah НТС One.</p>
<p><img width="600" height="412" alt="" src="/Users/wins/Library/Application Support/iPhone Simulator/5.0/Applications/2EAD8889-6482-48D4-80A7-9CCFD567123B/Library/Caches/htc-one-tab-7-concept-1(1).jpg"><br><br>
blah-blah (Hasan Kaymak) blah-blah HTC One Tab 7, blah-blah HTC One. <br><br>
blah-blah
 microSD.<br><br>
blah-blah Wi-Fi to 4G LTE.</p>
</p>
</body></html>

image enregistrée sous le nom htc-one-tab-7-concept-1 (1) .jpg

WINSergey
la source