Использование HTML и локальных изображений в UIWebView

164

В моем приложении есть UIWebView, который я хочу использовать для отображения изображения, которое будет ссылаться на другой URL.

я использую

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

Проблема в том, что изображение не загружается (то есть не может быть найдено), даже если оно добавлено в качестве ресурса в мой проект и скопировано в комплект.

Я пытался использовать NSBundle, чтобы получить полный путь к изображению и использовать его, и он все еще не отображается в веб-представлении.

Любые идеи?

Jasarien
источник
Я больше не могу сделать это с iPhone OS 3.0. :( Больше информации (StackOverflow.com).
Джо Д'Андреа
8
Почему голосование против? : /
Jasarien
5
Это не обязательно, что они злые. Может быть, у них была законная причина? Мы, вероятно, никогда не узнаем. Если бы у них была вежливость, чтобы объяснить, почему они отказались в комментарии ...
Jasarien
63
Необходимо обязательно написать комментарий при голосовании вниз.
Роберт
@Jasarien: мне нужна такая же функциональность. но я не могу понять, что должно быть передано в htmlString в [webView loadHTMLString: htmlString baseURL: baseURL] и как я помещаю <img src = "image.jpg" /> мое изображение в html.
iPhone

Ответы:

291

Использование относительных путей или файла: пути для ссылки на изображения не работают с UIWebView. Вместо этого вы должны загрузить HTML в представление с правильным baseURL:

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. то есть все, что он показывает на странице, это "tour.html"
Chewie The Chorkie
В качестве примечания, если вы пытаетесь загрузить файлы javascript, а не изображения, вам также нужно посмотреть на это: stackoverflow.com/a/3629479/385619
Willster
в случае Xamarin ad MonoTouch webvie.LoadHtmlString (strig, NSBundle.MainBundle.BundleUrl);
Эрик Симоник
1
Идеально работает в симуляторе, но не в моем устройстве
jose920405
46

Использовать это:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
Литу тв
источник
5
Но ваш ответ идентичен ответу, опубликованному 3 года назад ... Ваш ответ не предлагает ничего другого, его не нужно было публиковать, потому что принятый ответ уже охватывал то, что вы опубликовали.
Jasarien
13
Это удобная однострочная версия принятого ответа - не причинит вреда, если он будет здесь.
MusiGenesis
9
@Jasarien, ответ Адама Александра был единственным решением до августа 2009 года. Но в Max OS X версии 10.6 это новое свойство bundleURLбыло добавлено в NSBundle. Не нужно брать bundlePath и конвертировать в URL. Так что для людей, работающих в версиях выше 10.6, это дает лучшее решение.
Rineez
В последнее время в этом посте видна большая активность. И никто не заметил, почему это так?
Литу ТВ
24

Я тоже столкнулся с этой проблемой. В моем случае я имел дело с некоторыми изображениями, которые не были локализованы, а с другими - на нескольких языках. Базовый URL не получил изображения внутри локализованных папок для меня. Я решил это, сделав следующее:

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

Затем используйте imgHTMLTag в HTML-коде UIWebView при загрузке содержимого.

Я надеюсь, что это поможет любому, кто столкнулся с той же проблемой.

Антон
источник
1
Использование file://было то, что мне было нужно.
Итак,
Ницца, именно то, что мне было нужно
Rubberduck
8

попробуйте использовать строку изображения base64.

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

NSString *strEncoded = [data base64Encoding];   

<img src='data:image/png;base64,%@ '/>,strEncoded
пинг
источник
6

У меня была схожая проблема, но все предложения не помогли.

Однако проблема заключалась в самом * .png. У него не было альфа-канала . Каким-то образом Xcode игнорирует все файлы png без альфа-канала во время процесса развертывания.


источник
Что вы сделали, чтобы выбраться из этого? Вы нашли какое-нибудь решение? Я сталкиваюсь с той же проблемой. UIWebView не показывает изображения, так как не имеет альфа-канала.
spaleja
1
Я использовал Gimp для добавления альфа-канала в мои png-файлы. См. Docs.gimp.org/en/gimp-layer-alpha-add.html
3

Вы можете добавить папку (скажем, WEB с подпапками css, img и js и файлом test.html) в свой проект, выбрав « Добавить файлы в« MyProj »» и выбрав « Создать ссылки на папки» . Теперь следующий код позаботится обо всех упомянутых изображениях, CSS и JavaScript

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WEB/test.html" ofType:nil];
[webView  loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
zeeawan
источник
3

В Swift 3:

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

Это работало для меня, даже когда изображение было внутри папки без каких-либо изменений.

MrAn3
источник
2

Прочитав пару глав в Cookbok для программирования на iOS 6 и начав изучать программирование на target-c и iOS, я просто хотел бы добавить, что если кто-то собирается загружать ресурсы из пользовательского пакета и использовать его в веб-представлении , это может быть достигнуто следующим образом:

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

Свифт версия ответа Литу ТВ:

webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)
Муса Алматри
источник
1

Свифт версия Адама Александерса Цель C ответ:

let logoImageURL = NSURL(fileURLWithPath: "\(Bundle.main.bundlePath)/PDF_HeaderImage.png")
RJH
источник
0

Если вы используете относительные ссылки на изображения, то изображения не будут отображаться, поскольку все структуры папок не сохраняются после компиляции приложения iOS. Вместо этого вы можете преобразовать локальную веб- папку в пакет , добавив расширение имени файла .bundle .

Поэтому, если ваш локальный веб-сайт содержится в папке « www », его следует переименовать в « www.bundle ». Это позволяет сохранять папки с изображениями и структуру каталогов. Затем загрузите файл « index.html » в WebView в виде строки HTML с помощью baseURL (путь к www.bundle), чтобы разрешить загрузку относительных ссылок на изображения.

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 на моем сервере, который я загружаю в каталог документов. Я хочу, чтобы он отображал с локальным графиком в UIWebView, который я не мог заставить работать. Вот что я сделал:

  1. Скопируйте файл из NSBundle в локальный каталог документов
  2. Ссылка на файл в моем HTML-документе как «file: \\ filename.png»

Итак, при запуске скопируйте файл в каталог документов:

-(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
источник
-7

Мое комплексное решение (или учебник) для rss-ленты (получить в 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

WINSergey
источник