在UIWebView中使用HTML和本地图像


164

我的应用程序中有一个UIWebView,我想用它来显示将链接到另一个URL的图像。

我正在使用

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

问题在于,即使将图像作为资源添加到我的项目中并复制到捆绑包中,也无法加载(即找不到)。

我尝试使用NSBundle来获取图像的完整路径并使用它,但它仍未显示在Web视图中。

有任何想法吗?


从iPhone OS 3.0开始,我不再能够执行此操作。:( 更多信息(StackOverflow.com)
乔D'安德烈

8
为什么要投反对票?:/
Jasarien

5
他们不一定是邪恶的。也许他们有正当的理由?我们可能永远不会知道。如果他们能有礼貌地解释为什么他们在评论中投反对票...
Jasarien

63
写一个关于否决的评论应该是强制性的。
罗伯特

@Jasarien:我需要相同的功能。但我无法理解[webView loadHTMLString:htmlString baseURL:baseURL]中的htmlString应该传递什么,以及如何将我的图像<img src =“ image.jpg” />放入html中。
iPhone

Answers:


291

使用相对路径或文件:引用图像的路径不适用于UIWebView。相反,您必须使用正确的baseURL将HTML加载到视图中:

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

然后,您可以像这样引用您的图片:

<img src="myimage.png">

(从uiwebview重新访问


15
[[NSBundle mainBundle] bundleURL]我们可以将其用作bundleURL
Naveen Shan

2
这一切对我来说就是在我为htmlString定义的Web视图中给我一个字符串。即,页面上显示的全部是“ tour.html”
Chewie The Chorkie,2012年

作为旁注,如果您尝试加载与图像相对的javascript文件,则还需要查看以下内容:stackoverflow.com/a/3629479/385619
Willster 2014年

如果是Xamarin广告MonoTouch webvie.LoadHtmlString(strig,NSBundle.MainBundle.BundleUrl);
Erik Simonic 2014年

1
在模拟器中工作完美,但在我的设备中工作不完美
jose920405 '16

46

用这个:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];

5
但是您的答案与3年前发布的答案相同...您的答案没有什么不同,它不需要发布,因为接受的答案已经涵盖了您发布的内容。
Jasarien 2012年

13
这是已接受答案的便捷的单行版本-在此处使用它不会造成任何伤害。
MusiGenesis 2012年

9
@ Jasarien,Adam Alexander的回答是直到2009年8月的唯一解决方案。但是从Max OS X版本10.6开始,此新属性bundleURL已添加到NSBundle中。无需使用bundlePath并转换为URL。因此,对于使用高于10.6的版本的人来说,这是一个更好的解决方案。
rineez 2012年

最近在这篇文章中看到了很多-ve活动。而没有人指出为什么会这样?
Lithu电视

24

我也遇到了这个问题。就我而言,我正在处理一些未本地化的图像和其他一些(使用多种语言)的图像。基本网址对我来说没有使图像位于本地化文件夹中。我通过执行以下操作解决了这个问题:

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

然后,在加载内容时,在UIWebView HTML代码中使用imgHTMLTag。

我希望这可以帮助遇到相同问题的任何人。


1
使用file://是我所需要的。
因此,它

很好,正是我所需要的
Rubberduck '17

8

尝试使用base64图片字符串。

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

NSString *strEncoded = [data base64Encoding];   

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

6

我遇到了类似的问题,但所有建议都无济于事。

但是,问题出在* .png本身。它没有alpha通道。在部署过程中,Xcode会以某种方式忽略所有没有alpha通道的png文件


您是怎么做到的?您找到解决方案了吗?我正面临着同样的问题。UIWebView不显示图像,因为它没有Alpha通道。
spaleja

1
我使用Gimp将Alpha通道添加到png文件中。参见docs.gimp.org/en/gimp-layer-alpha-add.html

3

您可以通过选择将文件添加到“ MyProj”并选择创建文件夹引用,将文件夹(例如带有子文件夹css,img和js的WEB以及文件test.html)添加到项目中。现在,以下代码将处理所有引用的图像,css和javascript

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

3

在Swift 3中

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

即使图像没有任何修改就位于文件夹内,这也对我有用。


2

在阅读了iOS 6 Programming Cookbok中的几章内容并开始学习Objective-c和iOS编程之后,我想补充一下,如果要从自定义包中加载资源并在Web视图中使用它,可以这样完成:

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

然后,在您的html中,您可以使用“自定义”捆绑包作为基本路径来引用资源:

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

1

Swift版Lithu TV的答案:

webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)

1

Swift版本的Adam Alexanders Objective C答案:

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

0

如果您使用图像的相对链接,则图像将不会显示,因为在编译iOS应用程序后不会保留所有文件夹结构。您可以做的是将本地Web 文件夹转换为包,而不是添加' .bundle '文件扩展名。

因此,如果本地网站包含在文件夹“ www ”中,则应将其重命名为“ www.bundle ”。这样可以保留图像文件夹和目录结构。然后将“ index.html ”文件作为带有“ baseURL ”(设置为www.bundle路径)的HTML字符串加载到WebView中,以启用相对图像链接的加载。

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

0

这些答案确实对我有所帮助-特别是文件:\\ xxxxxxx.xxx,但我必须采取一种变通办法来显示图像。

就我而言,我的服务器上有一个HTML文件,我将其下载到documents目录。我希望它与无法工作的UIWebView中的本地图形一起显示。这是我所做的:

  1. 将文件从NSBundle复制到本地文档目录
  2. 在我的HTML文档中将文件引用为“ file:\\ filename.png”

因此,在启动时将文件复制到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);
}

-7

我为rss-feed(在RSSItems中获取)的复杂解决方案(或教程)仅在以下设备上有效:

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

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

}

在View控制器上

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

}

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

带有图像的任何HTML的一部分

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

为名称htc-one-tab-7-concept-1(1).jpg保存的图像

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.