Korzystanie z HTML i lokalnych obrazów w UIWebView

164

W mojej aplikacji mam UIWebView, którego chcę użyć do wyświetlenia obrazu, który będzie linkiem do innego adresu URL.

używam

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

Problem polega na tym, że obraz nie ładuje się (tj. Nie można go znaleźć), mimo że jest dodawany jako zasób w moim projekcie i jest kopiowany do pakietu.

Próbowałem użyć NSBundle, aby uzyskać pełną ścieżkę obrazu i używając tego, ale nadal nie pojawia się w widoku sieciowym.

Jakieś pomysły?

Jasarien
źródło
Od wersji iPhone OS 3.0 nie mogę już tego robić. :( Więcej informacji (StackOverflow.com).
Joe D'Andrea,
8
Dlaczego głosowanie negatywne? : /
Jasarien
5
Niekoniecznie jest to, że są złe. Może mieli uzasadniony powód? Prawdopodobnie nigdy się nie dowiemy. Gdyby tylko mieli uprzejmość, aby wyjaśnić, dlaczego głosowali w komentarzu ...
Jasarien
63
Pisanie komentarza do głosowania przeciwnego powinno być obowiązkowe.
Robert
@Jasarien: Potrzebuję tej samej funkcjonalności. ale nie rozumiem, co powinno być przekazywane w htmlString w [webView loadHTMLString: htmlString baseURL: baseURL] i jak umieścić <img src = "image.jpg" /> mój obraz w html.
iPhone

Odpowiedzi:

291

Używanie względnych ścieżek lub plików: ścieżki do odwoływania się do obrazów nie działa z UIWebView. Zamiast tego musisz załadować kod HTML do widoku z poprawnym baseURL:

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

Następnie możesz odwołać się do swoich obrazów w ten sposób:

<img src="myimage.png">

(z ponownego odwiedzenia uiwebview )

Adam Alexander
źródło
15
[[NSBundle mainBundle] bundleURL] możemy użyć tego jako bundleURL
Naveen Shan
2
Wszystko to dla mnie daje mi ciąg w moim widoku sieciowym, który zdefiniowałem dla mojego htmlString. tzn. wszystko, co pokazuje strona to „tour.html”
Chewie The Chorkie,
Na marginesie, jeśli próbujesz załadować pliki javascript, a nie obrazy, musisz również przyjrzeć się temu: stackoverflow.com/a/3629479/385619
Willster
w przypadku Xamarin ad MonoTouch webvie.LoadHtmlString (strig, NSBundle.MainBundle.BundleUrl);
Erik Simonic,
1
Działa
46

Użyj tego:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
Lithu TV
źródło
5
Ale Twoja odpowiedź jest identyczna z odpowiedzią opublikowaną 3 lata temu ... Twoja odpowiedź nie różni się niczym, nie musiała być opublikowana, ponieważ zaakceptowana odpowiedź obejmowała już to, co opublikowałeś.
Jasarien
13
To wygodna, jednowierszowa wersja zaakceptowanej odpowiedzi - nic się nie stanie, jeśli ją tutaj znajdziesz.
MusiGenesis
9
@Jasarien - odpowiedź Adama Alexandra była jedynym rozwiązaniem do sierpnia 2009 r. Jednak od wersji 10.6 systemu Max OS X ta nowa właściwość bundleURLzostała dodana w pakiecie NSBundle. Nie ma potrzeby wykonywania bundlePath i konwertowania do adresu URL. Więc dla osób pracujących w wersjach wyższych niż 10.6 daje to lepsze rozwiązanie.
rineez
widząc ostatnio dużo aktywności w tym poście… I nikt nie zauważył, dlaczego tak jest?
Telewizor Lithu
24

Właśnie napotkałem ten problem. W moim przypadku miałem do czynienia z niektórymi obrazami, które nie były zlokalizowane, a innymi, które były - w wielu językach. Podstawowy adres URL nie spowodował, że obrazy znajdowały się w zlokalizowanych folderach. Rozwiązałem to, wykonując następujące czynności:

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

Następnie użyj imgHTMLTag w kodzie HTML UIWebView podczas ładowania zawartości.

Mam nadzieję, że pomoże to każdemu, kto napotkał ten sam problem.

Anton
źródło
1
Używanie file://było tym, czego potrzebowałem.
So Over It
Niezłe, dokładnie to, czego potrzebowałem
Rubberduck,
8

spróbuj użyć łańcucha obrazu base64.

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

NSString *strEncoded = [data base64Encoding];   

<img src='data:image/png;base64,%@ '/>,strEncoded
Świst
źródło
6

Miałem podobny problem, ale wszystkie sugestie nie pomogły.

Jednak problemem był sam plik * .png. Nie miał kanału alfa . W jakiś sposób Xcode ignoruje wszystkie pliki png bez kanału alfa podczas procesu wdrażania.


źródło
Co zrobiłeś, żeby z tego wyjść? Czy znalazłeś jakieś rozwiązanie? Mam ten sam problem. UIWebView nie wyświetla obrazów, ponieważ nie ma kanału alfa.
spaleja
1
Użyłem Gimpa, aby dodać kanał alfa do moich plików png. Zobacz docs.gimp.org/en/gimp-layer-alpha-add.html
3

Możesz dodać folder (powiedzmy WEB z podfolderami css, img i js oraz plik test.html) do swojego projektu, wybierając opcję Dodaj pliki do „MyProj” i wybierając opcję Utwórz odniesienia do folderów . Teraz poniższy kod zajmie się wszystkimi wskazanymi obrazami, css i javascript

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

W Swift 3:

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

Działało to dla mnie nawet wtedy, gdy obraz znajdował się w folderze bez żadnych modyfikacji.

MrAn3
źródło
2

Po przeczytaniu kilku rozdziałów w Cookbok Programowanie na iOS 6 i rozpoczęciu nauki programowania w celu-c i iOS, chciałbym tylko dodać, że jeśli ktoś ma ładować zasoby z niestandardowego pakietu i używać go w widoku sieciowym można to zrobić w następujący sposób:

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

Następnie w swoim html możesz odwołać się do zasobu, używając pakietu „niestandardowego” jako ścieżki podstawowej:

body {
    background-image:url('img/myBg.png');
}
Lasse Christiansen
źródło
1

Szybka wersja odpowiedzi Lithu TV:

webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)
Musa almatri
źródło
1

Szybka wersja odpowiedzi Adama Alexandersa na cel C:

let logoImageURL = NSURL(fileURLWithPath: "\(Bundle.main.bundlePath)/PDF_HeaderImage.png")
RJH
źródło
0

Jeśli używasz linków względnych do obrazów, obrazy nie będą wyświetlane, ponieważ wszystkie struktury folderów nie są zachowywane po skompilowaniu aplikacji na iOS. Zamiast tego możesz przekonwertować lokalny folder sieciowy na pakiet , dodając plik.bundle rozszerzenie nazwy pliku ”.

Jeśli więc lokalna witryna znajduje się w folderze „ www ”, należy zmienić jego nazwę na „ www.bundle ”. Pozwala to na zachowanie folderów obrazów i struktury katalogów. Następnie załaduj plik „ index.html ” do WebView jako ciąg znaków HTML z „ baseURL ” (ustawionym na ścieżkę www.bundle), aby umożliwić ładowanie odnośników do obrazów względnych.

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
źródło
0

Te odpowiedzi pomogły mi - w szczególności plik: \\ xxxxxxx.xxx, ale musiałem zastosować obejście, aby wyświetlić obraz.

W moim przypadku mam na serwerze plik HTML, który pobieram do katalogu dokumentów. Chcę, aby wyświetlał się z lokalną grafiką w UIWebView, którego nie mogłem uruchomić. Oto co zrobiłem:

  1. Skopiuj plik z NSBundle do lokalnego katalogu dokumentów
  2. Odwołaj się do pliku w moim dokumencie HTML jako „plik: \\ nazwa_pliku.png”

Więc podczas uruchamiania skopiuj plik do katalogu dokumentów:

-(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
źródło
-7

Moje złożone rozwiązanie (lub samouczek) dla źródła rss (pobierz w RSSItems) działa tylko na urządzeniu:

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

i

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

}

na kontrolerze widoku

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

}

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

część dowolnego kodu HTML z obrazem

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

obraz zapisany dla nazwy htc-one-tab-7-concept-1 (1) .jpg

WINSergey
źródło