WebView loadHTMLString:baseURL: not loading css - ios

I have this this code:
NSURL *mainBundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
[webView loadHTMLString:htmlFile baseURL:mainBundleURL];
I know the htmlFile is correct. It has inside:
<link rel="stylesheet" type="text/css" href="stylesheet.css">
I also know the stylesheet.css in in the mainBundle. I checked the project.app contents.
Problem is that is the webview is empty. But if I use base Url as nil:
[webView loadHTMLString:htmlFile baseURL:nil];
The webview shows the content, but without the css file.
I have no idea why this is not working. Thanks in advance.

I solved this using the resourceURL property
NSURL *baseURL = [[NSBundle mainBundle] resourceURL];
and then [webView loadHTMLString:htmlFile baseURL:baseURL];
-Sal

Most examples reference baseUrl: nil but in order to access the CSS file you need to reference the bundle so that the <link rel="stylesheet" ... can access the file.
This is my solution in Swift 3:
let baseUrl : URL = Bundle.main.resourceURL! as URL
let htmlFile = Bundle.main.path(forResource: "*html file name*", ofType: "html")
let htmlString = try? String(contentsOfFile: htmlFile!, encoding: String.Encoding.utf8)
webView.loadHTMLString(htmlString!, baseURL: baseUrl)
Credit the Sal's answer for pointing this out.

Perhabs shouldStartLoadWithRequest method blocks your request. Try this:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([request.URL.absoluteString hasPrefix:#"file"]) {return YES;}
//deal with the request
}

Related

HTML Link from within a local HTML file in a UIWebView

Very new to XCode here
Basically, we have an app dependent on the UIWebView. When there is a valid network connection, we load a mobile web page into the UIWebView, if there is no connection, we will load a local version of the html web page. My scenario has to do with the offline or limited network connection scenario. When this offline scenario does occur, I am able to load my local html file just fine using the answer from this thread:
Load resources from relative path using local html in uiwebview
My problem comes in when click on a simple html link (which is also within my local app directory) within the local html file that is loaded. I have tried these, but when I click the link, nothing occurs, the link does not take me anywhere and the simulator will only allow me to copy the text:
<a href="file:///Sample.html">
<a href="file://Sample.html">
<a href="Sample.html">
<a href="/Sample.html">
<a href="Testing/Sample.html">
The sample.html webpage is in the same directory as the initial loaded html page. Not sure where I am going wrong, obviously missing something simple.
I suggest you re-examine your directory hierarchy. The behavior you are describing is what happens when the link you are trying to navigate to does not exist on the local device.
I ran the following small test:
Added a Webview to a view controller and loaded page1.html
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 10, 320, 300)];
[self.view addSubview:webView];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"page1" withExtension:#"html"];
NSString *html = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSURL *baseUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
[webView loadHTMLString:html baseURL:baseUrl];
page1.html
<html>
<body>
<h1>Page 1</h1>
Go to Page2
</body>
</html>
page2.html
<html>
<body>
<h1>Page 2</h1>
Back to Page 1
</body>
</html>
Image of the project Structure
The end result is, that it works. Clicking takes you from page 1 to page 2 and back again all using local files. If we change the link to:
which does not exist, you get the same behavior you are experiencing. That is you can only cut and copy and not actually go to the link.
For using resources from local file system try this solution like I did for displaying image on WebView.
-(NSString *)imagePath:(NSString *)fileName
{
if ([fileName isEqualToString:#""] == NO) {
NSLog(#"%#",fileName);
NSString *ImagePath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"png"];
ImagePath = [ ImagePath stringByReplacingOccurrencesOfString:#"/" withString:#"//"];
ImagePath = [ ImagePath stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
ImagePath = [#"file://" stringByAppendingString:ImagePath];
return ImagePath;
}
else
{
return #"";
}
}
Just assume you wnat to return the full path of your save HTML pages.
#Chris has an excellent example laid out, may be we need to update as follows :
let webView = UIWebView(frame: self.view.frame)
webView.delegate = self
self.view.addSubview(webView)
let urlString = Bundle.main.url(forResource: "Page1", withExtension: "html")
webView.loadRequest(URLRequest(url:urlString!))

UIWebView not loading local .html file

I a trying to view an .html file (index.html) that is stored in my Bundle (in my Supporting Files).
The .html file sits in a folder called HTML. My code is as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
_viewWeb.delegate = self;
NSString *path = [[NSBundle mainBundle]
pathForResource:#"index" ofType:#"html" inDirectory:#"HTML"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_viewWeb setScalesPageToFit:YES];
[self.viewWeb loadRequest:request];
}
My header file looks as follows:
#interface D6ViewController : UIViewController <UIWebViewDelegate>
{
IBOutlet UIWebView *viewWeb;
}
#property (weak, nonatomic) IBOutlet UIWebView *viewWeb;
#end
I synthesized property as viewWeb = _viewWeb. The viewcontroller holding the UIWebView loads fine but shows a white screen with no webpage. I have set the outlets in the IB.
Any ideas? Thanks,
You are using a relative path (hence the blue color of a folder). You can actually find the answer to this problem here Load resources from relative path using local html in uiwebview or below:
Drag the resource into your xcode project, you will get two options "create groups for any added folders" and "create folders references for any added folders". Select the "create folder references.." option.
The code below should work.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"/HTML"]];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
try this
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]isDirectory:NO]]];
In Swift:
func pathForResource(name: String?, ofType ext: String?, inDirectory subpath: String?) -> String?
- name: Name of Hmtl;
- ofType ext: extension for type of file. In this case "html";
- inDirectory subpath: the folder where are the file. In this case the file is in root folder;
let path = NSBundle.mainBundle().pathForResource("dados", ofType: "html", inDirectory: "root")
var requestURL = NSURL(string:path!);
var request = NSURLRequest(URL:requestURL);
webView.loadRequest(request)
You are wrong, here is the correct code:
var requestURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("index", ofType: "html", inDirectory: "www")!)
var request = NSURLRequest(URL:requestURL!)
myWebView.loadRequest(request)
You can use this If you are not saving your HTML file in any directory.If you are saving your HTML file in any directory then specify the directory name in "inDirectory" parameter.
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"privacy-Policy" ofType:#"html" inDirectory:nil];
NSData *htmlData = [NSData dataWithContentsOfFile:htmlFile];
[_webView loadData:htmlData MIMEType:#"text/html" textEncodingName:#"UTF-8" baseURL:[NSURL URLWithString:#""]];

UIWebview not fetching the linked CSS resource

I am trying to load a local html content into uiwebview. I already have the html content ready with me, and i am adding a reference a online css file to the content by the mechanism as shown in the code below. However, the problem i am facing is when i load the webview, there is no styling. Also, I verified in the Charles Proxy, there is no outgoing call for fetching iphone.css file to my base server. Ideally, while loading a html page, uiwebview should get all the referred resources, but for some reason unknown to me, it is not fetching the css file.
Please review and let me know if there is some issue with my code that i am not able to identify here?
NSString* htmlString = #"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"he\" lang=\"he\"><head><link type=\"text/css\" href=\"http://<base_server>/resources/iphone.css\" /><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body>%#</body></html>";
UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
NSLog(#"%#",[NSString stringWithFormat:htmlString,entry.body]);
[webview loadHTMLString:[NSString stringWithFormat:htmlString,entry.body] baseURL:[NSURL URLWithString:#"http://<base_server>/"]];
[self addSubview:webview];
It's hard to tell if there are any typos in the HTML with all of the double quote escaping going on in that string. Why don't you pull the HTML out of the string and into a file, read that file in and place your content in the body. There may be a mistake with the markup in that string. This would allow you to read it easier in a seperate file.
Something like:
NSError *error;
NSStringEncoding encoding;
NSString *htmlFilePath = [[NSBundle mainBundle] pathForResource: #"Sample"
ofType: #"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:htmlFilePath
usedEncoding:&encoding
error:&error];
NSString *html = [NSString stringWithFormat:htmlString, entry.body];
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webview loadHTMLString:html baseURL:baseURL];

How to load local html file into UIWebView

I'm trying to load a html file into my UIWebView but it won't work. Here's the stage: I have a folder called html_files in my project. Then I created a webView in interface builder and assigned an outlet to it in the viewController. This is the code I'm using to append the html file:
-(void)viewDidLoad
{
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"html" inDirectory:#"html_files"];
NSData *htmlData = [NSData dataWithContentsOfFile:htmlFile];
[webView loadData:htmlData MIMEType:#"text/html" textEncodingName:#"UTF-8" baseURL:[NSURL URLWithString:#""]];
[super viewDidLoad];
}
That won't work and the UIWebView is blank. I'd appreciate some help.
probably it is better to use NSString and load html document as follows:
Objective-C
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];
Swift
let htmlFile = NSBundle.mainBundle().pathForResource("fileName", ofType: "html")
let html = try? String(contentsOfFile: htmlFile!, encoding: NSUTF8StringEncoding)
webView.loadHTMLString(html!, baseURL: nil)
Swift 3 has few changes:
let htmlFile = Bundle.main.path(forResource: "intro", ofType: "html")
let html = try? String(contentsOfFile: htmlFile!, encoding: String.Encoding.utf8)
webView.loadHTMLString(html!, baseURL: nil)
Did you try?
Also check that the resource was found by pathForResource:ofType:inDirectory call.
EDIT 2016-05-27 - loadRequest exposes "a universal Cross-Site Scripting vulnerability." Make sure you own every single asset that you load. If you load a bad script, it can load anything it wants.
If you need relative links to work locally, use this:
NSURL *url = [[NSBundle mainBundle] URLForResource:#"my" withExtension:#"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
The bundle will search all subdirectories of the project to find my.html. (the directory structure gets flattened at build time)
If my.html has the tag <img src="some.png">, the webView will load some.png from your project.
by this you can load html file which is in your project Assets(bundle) to webView.
UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[web loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"test" ofType:#"html"]isDirectory:NO]]];
may be this is useful to you.
I guess you need to allocate and init your webview first::
- (void)viewDidLoad
{
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"html" inDirectory:#"html_files"];
NSData *htmlData = [NSData dataWithContentsOfFile:htmlFile];
webView = [[UIWebView alloc] init];
[webView loadData:htmlData MIMEType:#"text/html" textEncodingName:#"UTF-8" baseURL:[NSURL URLWithString:#""]];
[super viewDidLoad];
}
A Simple Copy-Paste code snippet:
-(void)LoadLocalHtmlFile:(NSString *)fileName onWebVu:(UIWebView*)webVu
{
[webVu loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:fileName ofType:#"html"]isDirectory:NO]]];
}
Note:
Make sure the html file's Target membership is checked otherwise following exception will get thrown :-
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:isDirectory:]: nil string parameter'
For Swift 3 and Swift 4:
let htmlFile = Bundle.main.path(forResource: "name_resource", ofType: "html")
let html = try! String(contentsOfFile: htmlFile!, encoding: String.Encoding.utf8)
self.webView.loadHTMLString(html, baseURL: nil)
UIWebView *web=[[UIWebView alloc]initWithFrame:self.view.frame];
//[self.view addSubview:web];
NSString *filePath=[[NSBundle mainBundle]pathForResource:#"browser_demo" ofType:#"html" inDirectory:nil];
[web loadRequest:[NSURLRequest requestWhttp://stackoverflow.com/review/first-postsithURL:[NSURL fileURLWithPath:filePath]]];
May be your HTML file doesn't support UTF-8 encoding, because the same code is working for me.
Or u can also these line of code:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"Notes For Apple" ofType:#"htm" inDirectory:nil];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[WebView loadHTMLString:htmlString baseURL:nil];
Here the way the working of HTML file with Jquery.
_webview=[[UIWebView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)];
[self.view addSubview:_webview];
NSString *filePath=[[NSBundle mainBundle]pathForResource:#"jquery" ofType:#"html" inDirectory:nil];
NSLog(#"%#",filePath);
NSString *htmlstring=[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
[_webview loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
or
[_webview loadHTMLString:htmlstring baseURL:nil];
You can use either the requests to call the HTML file in your UIWebview
Make sure "html_files" is a directory in your app's main bundle, and not just a group in Xcode.
A new way to do this using swift. The UIWebView is no more and WKWebView is the new class to load web pages, which ensures the Safari features to the web view.
import WebKit
let preferences = WKPreferences()
preferences.javaScriptCanOpenWindowsAutomatically = false
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
let webView = WKWebView(frame: self.view.bounds, configuration: configuration)
let request = NSURLRequest(URL: NSURL(string: "http://nshipster.com"))
webView.loadRequest(request)
Swift iOS:
// get server url from the plist directory
var htmlFile = NSBundle.mainBundle().pathForResource("animation_bg", ofType: "html")!
var htmlString = NSString(contentsOfFile: htmlFile, encoding: NSUTF8StringEncoding, error: nil)
self.webView.loadHTMLString(htmlString, baseURL: nil)
Here's Swift 3:
if let htmlFile = Bundle.main.path(forResource: "aa", ofType: "html"){
do{
let htmlString = try NSString(contentsOfFile: htmlFile, encoding:String.Encoding.utf8.rawValue )
messageWebView.loadHTMLString(htmlString as String, baseURL: nil)
}
catch _ {
}
}
[[NSBundle mainBundle] pathForResource:#"marqueeMusic" ofType:#"html"];
It may be late but if the file from pathForResource is nil you should add it in the Build Phases > Copy Bundle Resources.
if let htmlFile = NSBundle.mainBundle().pathForResource("aa", ofType: "html"){
do{
let htmlString = try NSString(contentsOfFile: htmlFile, encoding:NSUTF8StringEncoding )
webView.loadHTMLString(htmlString as String, baseURL: nil)
}
catch _ {
}
}
In Swift 2.0, #user478681's answer might look like this:
let HTMLDocumentPath = NSBundle.mainBundle().pathForResource("index", ofType: "html")
let HTMLString: NSString?
do {
HTMLString = try NSString(contentsOfFile: HTMLDocumentPath!, encoding: NSUTF8StringEncoding)
} catch {
HTMLString = nil
}
myWebView.loadHTMLString(HTMLString as! String, baseURL: nil)
Put all the files (html and resources)in a directory (for my "manual"). Next, drag and drop the directory to XCode, over "Supporting Files". You should check the options "Copy Items if needed" and "Create folder references". Next, write a simple code:
NSURL *url = [[NSBundle mainBundle] URLForResource:#"manual/index" withExtension:#"html"];
[myWebView loadRequest:[NSURLRequest requestWithURL:url]];
Attention to #"manual/index", manual is the name of my directory!!
It's all!!!! Sorry for my bad english...
=======================================================================
Hola desde Costa Rica. Ponga los archivos (html y demás recursos) en un directorio (en mi caso lo llamé manual), luego, arrastre y suelte en XCode, sobre "Supporting Files". Usted debe seleccionar las opciones "Copy Items if needed" y "Create folder references".
NSURL *url = [[NSBundle mainBundle] URLForResource:#"manual/index" withExtension:#"html"];
[myWebView loadRequest:[NSURLRequest requestWithURL:url]];
Presta atención a #"manual/index", manual es el nombre de mi directorio!!
When your project gets bigger, you might need some structure, so that your HTML page can reference files located in subfolders.
Assuming you drag your html_files folder to Xcode and select the Create folder references option, the following Swift code ensures that the WKWebView supports also the resulting folder structure:
import WebKit
#IBOutlet weak var webView: WKWebView!
if let path = Bundle.main.path(forResource: "sample", ofType: "html", inDirectory: "html_files") {
webView.load( URLRequest(url: URL(fileURLWithPath: path)) )
}
This means that if your sample.html file contains an <img src="subfolder/myimage.jpg"> tag, then the image file myimage.jpg in subfolder will also be loaded and displayed.
Credits: https://stackoverflow.com/a/8436281/4769344

Get current URL of UIWebView

I already tried getting the current URL of my UIWebView with: webview.request.URL.
Unfortunately the NSURL was empty. Anything wrong here? I am working with Xcode 3.2.2 beta 5.
The code above should be executed in the UIWebView delegate didStartLoad.
window.location via JS didn't work reliably for me, but this did:
currentURL = currentWebView.request.URL.absoluteString;
Credit:
http://mohrt.blogspot.com/2008/10/getting-url-from-uiwebview.html
here's the code I use to grab the url every time you navigate to a different link within the webview:
- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
self.url = aWebView.request.mainDocumentURL;
}
Matt's version is much cleaner. I recommend everyone to use that one instead of this
You could try this:
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:#"window.location"];
I too found that the approved answer above was not reliable.
But with a slight modification, it seems to work every time:
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:#"window.location.href"];
Note the addition of ".href" to the Javascript as this is hidden at the end of the line of code.
This is not correct, and will return a nil:
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:#"window.location"];
However, the code below can get a URL, but the url may not be the current URL:
NSString *url = _webView.request.URL.absoluteString;
The correct one is:
NSString *currentURL = [_webView stringByEvaluatingJavaScriptFromString:#"window.location.href"];
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSURL *currentURL = [[webView request] URL];
NSLog(#"%#",[currentURL description]);
}
Tried this for google search results on iPhone:
NSString* currentURL = webView.request.URL.absoluteString;
NSString* mainDocumentURL = webView.request.mainDocumentURL.absoluteString;
Both return the same string!
As UIWebView is deprecated, for WKWebview to get the current url is very simple.
webView.url
here the code i use :
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[[[webView request] URL] absoluteString]]];
I use the shouldStartLoadWithRequest event (UIWebViewDelegate) to catch URL updates. request.mainDocumentURL.absoluteString will get you the main web page's URL (which is normally what you want), while request.URL.absoluteString will include CSS and JavaScript includes.
This always works . .
NSString* url= [webView stringByEvaluatingJavaScriptFromString:#"window.location.href"];
implement delegate method,
- (BOOL)webView:(UIWebView *)webview shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *URL = request.URL.absoluteString; NSLog(#"%#",URL);
}
URL is the what you exactly needed.
IN Swift try this,
func webViewDidFinishLoad(webView: UIWebView){
println(WebView.request?.mainDocumentURL)
}
To get current URL of the WKWebView and UIWebview
Here is the code.
if (self.wkWebView) {
NSString *URL = self.wkWebView.title;
}else if(self.uiWebView) {
NSString *URL = self.uiWebView.request.title;
}

Resources