Використання HTML та локальних зображень у UIWebView


164

У моєму додатку є UIWebView, який я хочу використовувати для відображення зображення, яке посилається на інший URL.

Я використовую

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

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

Я намагався використовувати NSBundle, щоб отримати повний шлях зображення та його використання, і він все ще не відображається у веб-перегляді.

Будь-які ідеї?


Я більше не в змозі зробити це, як в iPhone OS 3.0. :( Більше інформації (StackOverflow.com).
Joe D'Andrea

8
Чому голосування проти? : /
Jasarien

5
Це не обов'язково, що вони злі. Може, у них були законні причини? Ми, мабуть, ніколи не дізнаємось. Якби вони мали ввічливість пояснити, чому вони проголосували в коментарі ...
Jasarien

63
Потрібно обов'язково написати коментар щодо голосування.
Роберт

@Jasarien: Мені потрібен такий же функціонал. але я не можу зрозуміти, що слід передати у htmlString у [webView loadHTMLString: htmlString baseURL: baseURL] і як я поміщаю <img src = "image.jpg" /> своє зображення в html.
iPhone

Відповіді:


291

Використання відносних шляхів або файлів: шляхи для посилання на зображення не працюють з UIWebView. Натомість вам потрібно завантажити HTML у подання з правильною базоюURL:

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 року. Але з версії 10.6 Max OS X це нове властивість bundleURLбуло додано в NSBundle. Не потрібно приймати bundlePath та перетворювати на URL. Тож для людей, які працюють у версіях, вищих за 10,6, це дає кращі рішення.
rineez

останнім часом побачила багато активності у цій публікації. І ніхто не зазначив, чому це?
Lithu TV

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 у своєму коді UIWebView HTML, коли ви завантажуєте вміст.

Я сподіваюся, що це допоможе кожному, хто зіткнувся з тією ж проблемою.


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 не відображає зображення, оскільки у нього немає каналу Alpha.
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]]];

3

У Swift 3:

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

Це працювало для мене навіть тоді, коли зображення знаходилось всередині папки без будь-яких модифікацій.


2

Прочитавши пару глав у програмуванні iOS 6 Cookbok та почавши вивчати програмування 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

Швидка версія відповіді телеканалу Lithu:

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

1

Швидка версія Адама Олександра Об'єктивна відповідь:

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

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 як "файл: \\ 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);
}

-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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.