I have a UIWebView in my app which I want to use to display an image which will link to another url.
I'm using
<img src="image.jpg" /> to load the image.
The problem is that the image doesn't load (ie. it can't be found) even though it's added as a resource in my project and is copied into the bundle.
I've tried using NSBundle to get the full path of the image and using that and it still doesn't show up in the web view.
Any ideas?
Using relative paths or file: paths to refer to images does not work with UIWebView. Instead you have to load the HTML into the view with the correct baseURL:
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webView loadHTMLString:htmlString baseURL:baseURL];
You can then refer to your images like this:
<img src="myimage.png">
(from uiwebview revisited)
Use this:
[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
I just ran into this problem too. In my case, I was dealing with some images that were not localized and others that were--in multiple languages. A base URL didn't get the images inside localized folders for me. I solved this by doing the following:
// 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];
Then, use imgHTMLTag in your UIWebView HTML code when you load the contents.
I hope this helps anyone who ran into the same problem.
try use base64 image string.
NSData* data = UIImageJPEGRepresentation(image, 1.0f);
NSString *strEncoded = [data base64Encoding];
<img src='data:image/png;base64,%# '/>,strEncoded
I had a simmilar problem, but all the suggestions didn't help.
However, the problem was the *.png itself. It had no alpha channel. Somehow Xcode ignores all png files without alpha channel during the deploy process.
In Swift 3:
webView.loadHTMLString("<img src=\"myImg.jpg\">", baseURL: Bundle.main.bundleURL)
This worked for me even when the image was inside of a folder without any modifications.
You can add folder (say WEB with sub folders css, img and js and file test.html) to your project by choosing Add Files to "MyProj" and selecting Create folder references. Now the following code will take care about all the referred images, css and javascript
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"WEB/test.html" ofType:nil];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
After having read a couple of chapters in the iOS 6 Programming Cookbok and started to learn objective-c and iOS programming, I would just like to add, that if one is going to load resources from a custom bundle and use that in a web view, it can be accomplished like this:
NSString *resourcesBundlePath = [[NSBundle mainBundle] pathForResource:#"Resources" ofType:#"bundle"];
NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcesBundlePath];
[self.outletWebView loadHTMLString:[html description] baseURL:[resourcesBundle bundleURL]];
Then, in your html you can refer to a resource using the "custom" bundle as your base path:
body {
background-image:url('img/myBg.png');
}
Swift Version of Lithu T.V's answer:
webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)
Swift version of Adam Alexanders Objective C answer:
let logoImageURL = NSURL(fileURLWithPath: "\(Bundle.main.bundlePath)/PDF_HeaderImage.png")
If you use relative links to images then the images won't display as all folder structures are not preserved after the iOS app is compiled. What you can do is convert your local web folder into a bundle instead by adding the '.bundle' filename extension.
So if you local website is contained in a folder "www", this should be renamed to "www.bundle". This allows the image folders and directory structure to be preserved. Then load the 'index.html' file into the WebView as an HTML string with 'baseURL' (set to www.bundle path) to enable loading relative image links.
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];
}
These answers did help me -- specifically the file:\\xxxxxxx.xxx, but I had to do a workaround to display the image.
In my case, I have an HTML file on my server which I download to the documents directory. I want to it to display with a local graphic in a UIWebView which I could not get to work. Here's what I did:
Copy the file from the NSBundle to the local documents directory
Reference the file in my HTML document as "file:\\filename.png"
So in startup copy the file to documents directory:
-(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);
}
My complex solution (or tutorial) for rss-feed (get in RSSItems) works only on device:
#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]);
}
}];
and
- (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
}
}
on View controller
- (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 item class
#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
part of any html with image
<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>
image saved for name htc-one-tab-7-concept-1(1).jpg
I'm trying to write code that loads a local html string into a UIWebView with images from the Assets.xcassets catalog.
Currently, I load the images from the main bundle, like this:
NSString *htmlString = [NSString stringWithFormat:#"<h1>My title</h1><img src='%#'/>", #"myImage1.png"];
[self.webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
However, this is very limiting in respect to using different retina versions of the images (#2 and #3).
I would like to load the images instead from the asset catalog, but can't figure out how to do it.
Provided the image name in the html string, how do I load the image from the assests into the webView, while supporting #2 and #3 retina versions?
Here Is Given Code Try it..
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webView loadHTMLString:htmlString baseURL:baseURL];
==> like thi some images :
=================================================================
This is how to load/use a local html with relative references.
Use the below given code.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"index" ofType:#"html" inDirectory:#"www"]];
[webview loadRequest:[NSURLRequest requestWithURL:url]];
Now all your relative links(like img/.gif, js/.js) in the html should get resolved.
Hi I want to load html and .js file from my project. These are the below steps i am following to load html file through framework but i am not able to hit html files.
Steps followed.
Created a framework which has webview as subview in it.
Created Resource.bundle and added all my html,.js files and images in the bundle.
When i add this framework into my project and try to access the image from the bundle i am not able to.
when i try to hit the html file i am not able to laod the html file in my webview.
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"Resource" ofType:#"bundle"];
NSString *htmlFile = [[NSBundle bundleWithPath:bundlePath] pathForResource:#"simple" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
NSURL *url=[[NSBundle mainBundle] bundleURL];
[webview loadHTMLString:htmlString baseURL:url];
[self addSubview:webview];
Can anyone tell me why this wont work and is this the right approach to follow?
I create a bundle with index.html that call a js with a simple alert, with this code i'm able to se the alert
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"BundleName" ofType:#"bundle"];
NSString *htmlFile = [[NSBundle bundleWithPath:bundlePath] pathForResource:#"index" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[_web loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
the html work in local? the webview is initialized?
I've this app which needs to store images shown in a webview locally, and show those stored images again inside the same webview.
This what I've gotten so far...
// After download button clicked... Store image from URL locally
NSURL *url = [NSURL URLWithString:myURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"filename.png"];
[urlData writeToFile:filePath atomically:YES];
}
// Get image path from Documents Directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"filename.png"];
// Display local html page
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"revistasPhotoswipe" ofType:#"html" inDirectory:#"www"]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_webView loadRequest:requestObj];
And in html file there's just a tag to show the image
<html>
<head></head>
<body><img src='filename.png' /></body>
</html>
Which is the right way to communicate the Documents Dir, with App Bundle and the HTML files to make this work? Another approach?
You can't use <body><img src='filename.png' /></body> because it references an object on a localserver that doesn't exist. You have a couple of options:
1. Javascript
A milliseconds after the page has loaded you should tell your webview to evaluate a javascript function.document["pictureIdFromProgam"].src = searchPic.src; as well as declaring your image element with <img src='throw.imgNotSet' id='pictureIdFromProgam'/>
2. String Manipulatoin
Another (less desirable, but quicker) option is to have your HTML file coded into an NSString and inserting the img link by using either replacing or %#s
Insertion:
[NSString stringWithFormat:#"<html><blah blah blah/><img src=%#/>",imagePathAsString];
and then you will be able to tell your webview to load the nsstring which contains the updated web content.
I built a simple ios app that loads a html downloaded from a server into a webview.
[self.webView loadHTMLString:notif.html baseURL:nil];
This works perfect. The problem is that i nedd to apply a local css file to the webview and I dont know how to do it.
I tried doing it this way, but the styles are not being applied.
NSString *HTML_HEADER=#"<HTML><HEAD><link rel='stylesheet' href='style.css' type='text/css'></HEAD><BODY>";
NSString *HTML_FOOTER=#"</BODY></HTML>";
NSString *htmlString = [NSString stringWithFormat:#"%#%#%#",HTML_HEADER,notif.html,HTML_FOOTER];
NSLog(#"htmlString %#", htmlString);
[self.webView loadHTMLString:htmlString baseURL:nil];
Any idea?
Thanks
UPDATE:
I tried to do the following:
NSString *HTML_HEADER=#"<HTML><HEAD><link rel='stylesheet' href='#FILE1#' type='text/css'></HEAD><BODY>";
NSString *HTML_FOOTER=#"</BODY></HTML>";
NSString *cssFilePath = [[NSBundle mainBundle] pathForResource:#"style" ofType:#"css"];
NSString *html_header_with_files = [HTML_HEADER stringByReplacingOccurrencesOfString:#"#FILE1#" withString:cssFilePath];
NSString *htmlString = [NSString stringWithFormat:#"%#%#%#",html_header_with_files,notif.html,HTML_FOOTER];
NSLog(#"htmlString %#", htmlString);
[self.webView loadHTMLString:htmlString baseURL:nil];
And in Build Phases i have added the style.css
UPDATE 2:
I also check if the style.css exists with
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"style" ofType:#"css"];
NSLog(#"\n\nthe string %#",filePath);
The reason is CSS and JS files not available at runtime for render in HTML.
You need to take care of some points:
All CSS/JS/HTML files must be added to Project Properties >> Build Phases >> Copy Bundle Resources.
Check that all files are added if not then manually add those files.
All files are should be placed in the same folder, so that reference file path will be available at run time.
Instead of using directly file names, I will prefer you to use marker. Use symbols as a marker to replace with actual path of CSS and JS files.
For example:
NSString *HTML_HEADER=#"<HTML><HEAD><link rel='stylesheet' href='#FILE1#' type='text/css'></HEAD><BODY>";
NSString *HTML_FOOTER=#"</BODY></HTML>";
NSString *cssFilePath = [[NSBundle mainBundle] pathForResource:#"style" ofType:#"css"];
NSString *html_header_with_files = [HTML_HEADER stringByReplacingOccurrencesOfString:#"#FILE1#" withString:cssFilePath];
NSString *htmlString = [NSString stringWithFormat:#"%#%#%#",html_header_with_files,notif.html,HTML_FOOTER];
NSLog(#"htmlString %#", htmlString);
[self.webView loadHTMLString:htmlString baseURL:nil];
In above example I have replace style.css string from html part and add marker #FILE1#.
This marker is relative url to file style.css and it will be replace before html load in webView.
So whenever you would like to load html to webView, load all resource files from their relatives urls.
Here HTML_HEADER will be replace with actual path for all resources files.
You can import files (as CSS, JS ...) even without putting them into "Copy bundle resources", so you can just download CSS and use it during run of your app.
Trick is in setting "baseURL" parameter, which becomes root directory for your UIWebView.
// HTML file
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:htmlFileName ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
// root directory
NSURL *rootDir = [[NSBundle mainBundle] bundleURL];
[self.webView loadHTMLString:htmlString baseURL:rootDir];
Then, when you say
<link rel="stylesheet" type="text/css" href="style.css">
in your HTML file, app will look for style.css in rootDir directory (in this case, [[NSBundle mainBundle] bundleURL] )
I finally find the solution.
NSString *HTML_HEADER=#"<HTML><HEAD><link rel='stylesheet' href='#FILE1#' type='text/css'></HEAD><BODY>";
NSString *HTML_FOOTER=#"</BODY></HTML>";
NSString *cssFilePath = [[NSBundle mainBundle] pathForResource:#"style" ofType:#"css"];
NSString *html_header_with_files = [HTML_HEADER stringByReplacingOccurrencesOfString:#"#FILE1#" withString:cssFilePath];
NSString *htmlString = [NSString stringWithFormat:#"%#%#%#",html_header_with_files,notif.html,HTML_FOOTER];
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSLog(#"htmlString %#", htmlString);
[self.webView loadHTMLString:htmlString baseURL:baseURL];
Its necessary to specify the bundlePath in loadHTMLString:
The solution is a combination of the two answers given by #Kampai and #itzprintz