Uso de HTML e imágenes locales dentro de UIWebView

164

Tengo un UIWebView en mi aplicación que quiero usar para mostrar una imagen que se vinculará a otra url.

Estoy usando

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

El problema es que la imagen no se carga (es decir, no se puede encontrar) a pesar de que se agrega como un recurso en mi proyecto y se copia en el paquete.

Intenté usar NSBundle para obtener la ruta completa de la imagen y usar eso y aún no aparece en la vista web.

¿Algunas ideas?

Jasarien
fuente
Ya no puedo hacer esto a partir del iPhone OS 3.0. :( Más información (StackOverflow.com).
Joe D'Andrea
8
¿Por qué el voto negativo? : /
Jasarien
55
No es necesariamente que sean malvados. Tal vez tenían una razón legítima? Probablemente nunca lo sabremos. Si tan solo tuvieran la cortesía de explicar por qué votaron en contra en un comentario ...
Jasarien
63
Debería ser obligatorio escribir un comentario en un voto negativo.
Robert
@Jasarien: necesito la misma funcionalidad. pero no puedo entender qué se debe pasar en htmlString en [webView loadHTMLString: htmlString baseURL: baseURL] y cómo pongo <img src = "image.jpg" /> mi imagen en html.
iPhone

Respuestas:

291

Uso de rutas o archivos relativos: las rutas para referirse a imágenes no funcionan con UIWebView. En su lugar, debe cargar el HTML en la vista con la baseURL correcta:

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

Luego puede referirse a sus imágenes de esta manera:

<img src="myimage.png">

(de uiwebview revisited )

Adam Alexander
fuente
15
[[NSBundle mainBundle] bundleURL] podemos usar esto como bundleURL
Naveen Shan
2
Todo lo que esto hace por mí es darme una cadena en mi vista web que definí para mi htmlString. es decir, todo lo que muestra en la página es "tour.html"
Chewie The Chorkie
Como nota al margen, si está intentando cargar archivos javascript en lugar de imágenes, también deberá ver esto: stackoverflow.com/a/3629479/385619
Willster
en el caso de Xamarin ad MonoTouch webvie.LoadHtmlString (strig, NSBundle.MainBundle.BundleUrl);
Erik Simonic
1
Trabajo perfecto en el simulador, pero no en mi dispositivo
jose920405
46

Utilizar este:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
Lithu TV
fuente
55
Pero su respuesta es idéntica a la respuesta publicada hace 3 años ... Su respuesta no ofrece nada diferente, no fue necesario publicarla porque la respuesta aceptada ya cubría lo que publicó.
Jasarien
13
Es una versión conveniente de una línea de la respuesta aceptada: no hay daño al tenerla aquí.
MusiGenesis
9
@Jasarien esa respuesta de Adam Alexander fue la única solución hasta agosto de 2009. Pero a partir de Max OS X versión 10.6, esta nueva propiedad bundleURLse agregó en NSBundle. No es necesario tomar bundlePath y convertir a URL. Entonces, para las personas que trabajan en versiones superiores a la 10.6, esto ofrece una mejor solución.
rineez
viendo mucha actividad reciente en esta publicación recientemente ... ¿Y nadie notó por qué?
Lithu TV
24

Me encontré con este problema también. En mi caso, estaba tratando con algunas imágenes que no estaban localizadas y otras que sí lo estaban, en varios idiomas. Una URL base no obtuvo las imágenes dentro de las carpetas localizadas para mí. Resolví esto haciendo lo siguiente:

// 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];

Luego, use imgHTMLTag en su código HTML UIWebView cuando cargue el contenido.

Espero que esto ayude a cualquiera que haya tenido el mismo problema.

Anton
fuente
1
Usar file://era lo que necesitaba.
So Over It
Bonito, exactamente lo que necesitaba
Rubberduck
8

intente usar una cadena de imagen base64.

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

NSString *strEncoded = [data base64Encoding];   

<img src='data:image/png;base64,%@ '/>,strEncoded
Silbido
fuente
6

Tuve un problema similar, pero todas las sugerencias no ayudaron.

Sin embargo, el problema era el * .png mismo. No tenía canal alfa . De alguna manera, Xcode ignora todos los archivos png sin canal alfa durante el proceso de implementación.


fuente
¿Qué hiciste para salir de esto? ¿Encontraste alguna solución? Estoy enfrentando el mismo problema. UIWebView no muestra imágenes ya que no tenía canal alfa.
spaleja
1
Usé Gimp para agregar un canal alfa a mis archivos png. Ver docs.gimp.org/en/gimp-layer-alpha-add.html
3

Puede agregar carpetas (digamos WEB con subcarpetas css, img y js y archivo test.html) a su proyecto seleccionando Agregar archivos a "MyProj" y seleccionando Crear referencias de carpeta . Ahora el siguiente código se ocupará de todas las imágenes referidas, CSS y JavaScript

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

En Swift 3:

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

Esto funcionó para mí incluso cuando la imagen estaba dentro de una carpeta sin ninguna modificación.

MrAn3
fuente
2

Después de leer un par de capítulos en el Cookbok de Programación de iOS 6 y comenzar a aprender la programación de Objective-C y iOS, me gustaría agregar que si uno va a cargar recursos de un paquete personalizado y usarlo en una vista web , se puede lograr así:

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

Luego, en su html, puede referirse a un recurso usando el paquete "personalizado" como su ruta base:

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

Versión rápida de la respuesta de Lithu TV:

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

Versión rápida de Adam Alexanders Objetivo C respuesta:

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

Si usa enlaces relativos a imágenes, las imágenes no se mostrarán, ya que no se conservan todas las estructuras de carpetas después de compilar la aplicación iOS. Lo que puede hacer es convertir su carpeta web local en un paquete agregando la extensión de nombre de archivo ' .bundle '.

Por lo tanto, si su sitio web local está contenido en una carpeta " www ", se debe cambiar el nombre a " www.bundle ". Esto permite preservar las carpetas de imágenes y la estructura de directorios. Luego cargue el archivo ' index.html ' en WebView como una cadena HTML con ' baseURL ' (configurado en la ruta www.bundle) para permitir cargar enlaces de imagen relativos.

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
fuente
0

Estas respuestas me ayudaron, específicamente el archivo: \\ xxxxxxx.xxx, pero tuve que hacer una solución para mostrar la imagen.

En mi caso, tengo un archivo HTML en mi servidor que descargo al directorio de documentos. Quiero que se muestre con un gráfico local en un UIWebView que no pude poner a trabajar. Esto es lo que hice:

  1. Copie el archivo del NSBundle en el directorio de documentos locales.
  2. Hacer referencia al archivo en mi documento HTML como "archivo: \\ filename.png"

Entonces, en el inicio, copie el archivo al directorio de documentos:

-(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);
}
DoctorG
fuente
-7

Mi solución compleja (o tutorial) para rss-feed (entrar en RSSItems) solo funciona en el dispositivo:

#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]);
                               }
                           }];

y

- (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
}

}

en el controlador de vista

- (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];

}

clase de elemento 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

parte de cualquier html con imagen

<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>

imagen guardada para nombre htc-one-tab-7-concept-1 (1) .jpg

WINSergey
fuente