Cargue recursos desde la ruta relativa utilizando html local en uiwebview

121

Tengo una aplicación iOS muy simple con una uiwebview cargando una página de prueba muy simple (test.html):

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

Cargo este archivo test.html en mi vista 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];

Esto funciona bien si hago referencia a la imagen sin la ruta relativa y pongo la imagen referenciada en la ruta raíz en Objetivos -> Copiar recursos del paquete dentro de XCode, sin embargo, no puedo hacer que funcione con la ruta relativa como se muestra en mi archivo html . Debe haber una manera de hacer esto, tengo muchas imágenes, css, archivos javascript que quiero cargar en la vista web y me gustaría no tener que tener todo en la raíz y cambiar todas las referencias en mi web aplicación

Matt Palmerlee
fuente

Respuestas:

286

Así es como cargar / usar un html local con referencias relativas.

  1. Arrastre el recurso a su proyecto xcode (arrastré una carpeta llamada www desde mi ventana del buscador), obtendrá dos opciones "crear grupos para cualquier carpeta agregada" y "crear referencias de carpetas para cualquier carpeta agregada".
  2. Seleccione la opción "crear referencias de carpeta ...".
  3. Use el siguiente código dado. Debería funcionar como un encanto.

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

Ahora todos sus enlaces relativos (como img / .gif, js / .js) en el html deberían resolverse.

Swift 3

    if let path = Bundle.main.path(forResource: "dados", ofType: "html", inDirectory: "root") {
        webView.load( URLRequest(url: URL(fileURLWithPath: path)) )
    }
sdbrain
fuente
1
Super y Up votaron! ¿Alguien puede explicar por qué "crear referencias de carpeta en lugar de" crear grupos para cualquier carpeta agregada "?
Sean
3
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
2
¿Qué pasa si el directorio tiene n carpetas de profundidad? ¿Está bien pasar una cadena como @"www/app"para el directorio arg?
Ray
1
¿Qué pasa si cargamos el html de los documentos, no del paquete?
chipbk10
@Sean XCode almacena de manera predeterminada todos los archivos agregados en la carpeta raíz, los grupos son solo para hacer que su árbol de proyectos se vea bien. Las referencias de carpeta en realidad copian el contenido tal cual, conservando la estructura del directorio. Eso es bastante esencial si desea que sus rutas relativas funcionen en el dispositivo de la misma manera que lo hacen en su máquina de oficina.
Combuster
24

En 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
fuente
Gracias por el código Swift. Funcionó bien junto con la respuesta aceptada
Bala Vishnu
¡Bienvenidos! :.) @Bala Vishnu
Weles
Funciona muy bien, tuve que desenvolver el requestURLsin embargo.
RRikesh
5

Metí todo en una línea (mal, lo sé) y no tuve problemas con eso:

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" 
                                                                                                         ofType:@"html"]
                                                             isDirectory:NO]]];         
PengOne
fuente
1
En el proyecto XCode para su imagen en el nodo de destino, ¿utiliza "Relativo al proyecto" o "Relativo al grupo de cerramiento"? Estaba usando Relativo para proyectar porque en el cuadro de diálogo obtener información, la ruta que se muestra cuando elijo Relativo para proyectar parece correcta. Sin embargo, parece cargar la imagen correctamente cuando elijo en relación con el grupo adjunto. Ahora solo voy a hacer que mi página completa funcione correctamente con javascript y css y todo, ¡gracias!
Matt Palmerlee
Ugh! Esta uiwebview es tan frágil que comencé a agregar lentamente pruebas más complejas a mi página de prueba (es decir, configurar la imagen con css en lugar de en línea en la etiqueta img) y no funcionaba, así que volví a lo que tenía originalmente y no funcionó No trabajes de nuevo! ¿Tal vez estoy lidiando con algún tipo de almacenamiento en caché en mi uiwebview?
Matt Palmerlee
5

Simplemente hago esto:

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

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

Donde "index.html" hace referencia relativamente a imágenes, CSS, javascript, etc.

McStopher viejo
fuente
2

Respuesta rápida 2.

La referencia de clase UIWebView desaconseja el uso de webView.loadRequest (solicitud):

No use este método para cargar archivos HTML locales; en su lugar, use loadHTMLString: baseURL :.

En esta solución, el html se lee en una cadena. La url del html se usa para calcular la ruta y la pasa como una url 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)
Este no soy yo
fuente
Si este es el caso, sería bueno referirse a dónde en el manual aconseja esto e insertar un extracto de esa página; parece muy sin contexto en este momento.
Ben Cox
El comentario de Apple está en la página Método de instancia para loadRequest:
Jeff
0

Regresé y probé y volví a probar esto, parece que la única forma en que puedo hacer que funcione (ya que tengo algunos archivos en la carpeta img y algunos en js / css, etc.) no es use una ruta relativa a mi imagen en el html y haga que todo haga referencia a la carpeta del paquete. Qué lástima :(.

<img src="myimage.png" />
Matt Palmerlee
fuente
0

La respuesta de @ sdbrain en 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
fuente
-1

En Swift 3.01 usando WKWebView:

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

Esto se ajusta a algunos de los cambios de sintaxis más finos en 3.01 y mantiene la estructura de directorios en su lugar para que pueda incrustar archivos HTML relacionados.

Bently Bobo
fuente
¿No se eliminó el prefijo NS para los tipos de base clave desde 3.x? Eso me sirvió, ¡gracias! let localURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "mapa_procesos")!) webView.loadRequest(URLRequest(url: localURL))
Eduardo Gómez