In my app I have a UIWebView-based view controller showing info and credits about the app itself. As part of the info, the app version is displayed, as retrieved from the infoDictionary of the mainBundle. So this string is not in the original HTML; it is set programmatically, by replacing a placeholder.
Therefore the sequence is:
1) I load the HTML into a NSString
2) I replace the placeholder with the actual version
3) I show the resulting string in UIWebView by invoking method loadHTMLString:baseURL:
The HTML also has hyperlinks to some web pages in the internet.
Everything is fine, but for this problem:
If I touch a hyperlink, and therefore navigate to the corresponding web page, I will not be able to go back to my original info page (canGoBack returns NO, goBack does nothing).
Any suggestion?
Thanks in advance.
In the end, I have found a satisfactory solution, that I would like to share.
1) I changed the HTML code of my info page, by inserting the following code where I want to show the app version:
<p>App version:
<script type="text/javascript">
var args = document.location.search.substring(1).split("&");
for (var i in args) {
var nameValue = args[i].split("=");
if (nameValue[0] == "version")
var version = nameValue[1];
}
if (version)
document.write(version);
</script>
</p>
This piece of code will parse the query part of the URL, looking for a "version=<version>" argument, and use its value to show the app version.
2) When preparing the URL to be used by the UIWebView, I retrieve the app version from the main bundle:
NSString* version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
Then I append it at the end of my URL string:
NSString* urlString = [NSString stringWithFormat:#"<my_info_page>.html?version=%#", version];
3) Finally, I use the UIWebView to show the page:
NSURL* url = [[NSURL alloc] initWithString:urlString];
NSURLRequest* request [[NSURLRequest alloc] initWithUrl:url];
[mWebView loadRequest:urlRequest];
[urlRequest release];
[url release];
where mWebView is an IBOutlet, of type UIWebView, properly connected to the web view in the XIB file.
It works correctly on my iPhone 4, including the back/forward functions of the web view when following hyperlinks, while keeping the user inside the app.
I would break out of the app and load Safari in this case:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
[[UIApplication sharedApplication] openURL:request.URL];
return NO;
}
The only downside is that the user comes out of your app. You could put an alertview in that method to warn them first...
Alternatively, you'll have to code your own back button.
Related
i have created webview in my app,
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"SimpleCall" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[webview loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];
[self.view addSubview:webview];
now i want to send a data to webview when webview starts load.is there any property for uiwebview?
thanks advance.
you must set the delegate UIWebViewDelegate property on your UIWebView, for example:
webView.delegate = self;
where self conforms to UIWebViewDelegate protocol and implement callback method webViewDidStartLoad (check docs) if you really want to do something when web view starts load. Then, you implement the method:
- (void)webViewDidStartLoad:(UIWebView *)webView {
//you can do something in here, but DON'T call any loaders of webView's - loadHTML or reload, cause this will result in a loop
}
But I doubt that will solve your problem - first of all you probably want to do something when web view finishes. Second - can you elaborate more on what you mean by:
send data to web view
DISCLAIMER: as of iOS 8 and higher you should use WKWebView instead.
EDIT: as clarified in comments you want to update dynamically html contents. In WKWebView docs you can read that there is no option to do that (i.e. dynamically insert options from your NSArray to loaded html string). You have to manually update your html string and then reload WKWebView with new, updated html. Reloading whole html just to update one feature is probably not an option here, so better store the webpage loaded on the server and update dynamically (when web page is updated with new options) by calling:
[webView reload];
Requirement is to load an HTML form in UIWebView and Access the values filled in that form in Objective-C.
So I was wondering if that's even possible. If so, how?
Thanks.
You can use [UIWebView stringByEvaluatingJavascriptFromString:] method.
use this code..
callJsWithObjectiveC
create JS file demo.js and add code
var hello = function(str){ return str; };
add UIWebView => To embed JavaScript in a dummy html file and load that into the UIWebView
[self.webView loadHTMLString:#"<script src=\"demo.js\"></script>" baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] resourcePath]]];
Here is the code to make JS call
NString *str=#"hi JavaScript";
NSString *function = [[NSString alloc] initWithFormat: #"hello(%#)", str];
NSString *result = [webView stringByEvaluatingJavaScriptFromString:function];
Now, there is one important safety tip to make this actually work: The UIWebView must actually be loaded a view. It doesn’t have to be visible, but in order for the WebKit engine to execute the JS, it must be on a view.
I have an iOS app which has XML file, that holds data for an app. That file contains links for web pages. For some reason, when I try to display this links with UIWebView, its not showing. There is white screen with black rectangle -
I know this problem is in my web links, but its perfectly correct when I try to open it in Mac or Windows browsers (in fact, I just copy-paste it from Wiki). For example, there is one of my links: http://ru.wikipedia.org/wiki/Московский_Кремль
And there is my code. It simple, but it do work when i test it with other link, like: http://apple.com
Code is below:
-(void)loadWebView{
NSURL *urlik = [NSURL URLWithString:self.entityLinkToWiki];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:urlik];
[self.myWebView loadRequest:requestObj];
}
// Note: self.entityLinkToWiki look like shown above - http://ru.wikipedia.org/wiki/Московский_Кремль
Of course I just don't want to force user to quit app and open link in Safari. Is there any way to show my stored web links in internal browser? And why is there such strange error? I mean links, that pretty fine in PC/Mac browsers doesn't work here?
UPDATED.
Guys, that was my fault and i terribly sorry for confusing you, and thank you for help. The problem is here: when i try to pass link string from one controller to another, somehow it lose part of text, and finally self.entityLinkToWiki = Московский_Кремль, not http://ru.wikipedia.org/wiki/Московский_Кремль as it should be!
My app have structure of table view, firstly, it load tableview, after that it pass values from XML which depends of indexPath.row. All values except web links works just fine, and i will explain the way i did this. As you request, there is part of web link in xml file:
<webpage>http://ru.wikipedia.org/wiki/Московский_Кремль</webpage>
To get that, i did following:
In "first" (tableView list) controller i pass values like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSString *string = [[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:#"description"];
DetailViewController *detailController = segue.destinationViewController;
detailController.descriptionStringShort =string;
....a lot of code here
detailController.fourthPhotoString = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:#"imageFourth"];
detailController.webLink = [[self.listOfPlaceDetails objectAtIndex:indexPath.row]
objectForKey:#"webpage"];
}
}
Image link has nothing to do with web link, i just post it, so you get picture that i pass values in this way and it work fine. Then, i pass values from "detail" controller to controller, that finally have UIWebView:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
.... a lot of code here
if ([segue.identifier isEqualToString:#"WebSegue"]){
WebViewController *webController = segue.destinationViewController;
webController.entityLinkToWiki = self.webLink;
NSLog(#"WebSegue link is %#", self.webLink);
}
}
And NSLog says, that self.webLink is already - Московский_Кремль (incorrect value). Therefore, i didn't get correct link for my UIWebView. So now, my question is - how to get correct link passing it like i did? I don't want to bother load it from XML file in final controller, because i need information of indexPath.row, to get correct value (i have a lot of entities in XML file).
Thank you for any help you provide, and sorry about first post (in which i didn't bother to look at console and see, that my link was incorrect).
You have asked multiple questions. If you just want to open the Kremlin link in your browser - Use NSUTF8StringEncoding.
NSString doesn't have any function built in that really does URL encoding properly, but this one works for extended characters. This will definitely handle your foreign characters. I tested the following -
- (void) viewDidLoad{
[super viewDidLoad];
self.myWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.myWebView.delegate = self;
NSString *myString = #"http://ru.wikipedia.org/wiki/Московский_Кремль";
NSURL *urlik = [NSURL URLWithString:[myString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:urlik];
[self.myWebView loadRequest:requestObj];
[self.view addSubview:self.myWebView];
}
I have an app where on the very last UIViewController there is a UIWebView... the user navigates through the app and at the very end they can transition (modal) to the final UIViewController with a UIWebView... in it's viewDidLoad I have the UIWebView load the page.
The problem is it takes about 8 seconds to load this page and that annoys users.
How can I load the UIWebView way ahead of time (like when the app is first launched!) if that UIViewController hasn't even been presented yet?
I had your same problem for UIWebView inside a UIPageViewController and I found a better solution.
If you are in FirstViewController and you have your webView in your SecondViewController put the loadHTMLString or loadRequest method in the viewDidLoad of your SecondViewController and call [secondViewController.view layoutSubviews] for start loading in your FirstViewController.
Ex:
FirstViewController
-(void)viewDidLoad{
[super viewDidLoad];
// _secondViewController -> An instance of SecondVieController
[_secondViewController.view layoutSubviews];
}
SecondViewController
-(void)viewDidLoad{
[super viewDidLoad];
NSURL *url =[NSURL URLWithString:#"http://www.google.it"];
NSURLRequest *request =[NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
What u can do is, load the html string
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:self.path ofType:#"htm"];
NSError * error;
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:&error];
and when u display the webView load this content in your webView
[self.webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
then your webview need only render your content and doesn't load the data
/// In Swift 2.0
do{
let path = NSBundle.mainBundle().pathForResource("theName", ofType: "html")!
let html = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
webView.loadHTMLString(html, baseURL: nil)
}catch{
print("Error is happend")
}
Note: It works the same way for WKWebView
Not sure how much work you want to do for this but I think you could cache/store the data from the URL in something like a NSDictionary, or something similar, using [NSUserDefaults standardUserDefaults] and use that information before actually loading the page.
So, load the first time you use it, after it has been seen then store the data using NSUserDefaults. Next time you go to this page, load from the NSUserDefaults first and call the URL/API in the back ground then update NSUserDefaults with this new data.
If you are requesting or pulling specific information each time, then I don't think this will work. If that is your case, you can probably try loading the data/website in an earlier view controller (probably one that takes the user a while to navigate to) and then send that data to the webview. Something like delegate/protocol or maybe even NSNotificationCenter. Hope this helps.
UIWebView is very tricky object. Simple answer would be: no you can't.
UIWebView won't load a document or an URL if it is not in views hierarchy.
Don't try doing it in different thread/queue either.
What you can do is to add UIWebView to the views hierarchy at the very beginning (as you've mentioned) and then pass it to the last view controller with preloaded data. This may work, but it's not an elegant way.
Side questions is: why does it take 8 secs to load a page? Maybe you can download the content of this page earlier? Is it static or dynamic?
I'm trying to append some HTML to a UIWebView. It doesn't work and instead overwrites the existing HTML, since oldHTML below is always empty. The HTML string starts off as
<html><font color="0x0000FF">Blue text</font></html>
Code:
NSString *oldHTML = [myWebView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerHTML"];
NSString *html = [NSString stringWithFormat:#"%#%#%#%#", #"<html>", oldHTML, htmlToAdd, #"</html>"];
[myWebView loadHTMLString:html baseURL:nil];
So my questions are:
Is it even possible to get the html from a UIWebView?
If so, why does the first line fail/what is the correct method?
Is there a better way to append HTML to a UIWebView?
Thanks for any help.
I suspect at the point you're trying to get the old html, your page hasn't completed loading yet, which is why it's returning a blank string.
Try creating and assigning a UIWebViewDelegate for your view that implements webViewDidFinishLoad: and putting your code above in that function - oldHTML should be non-blank at that point.
As for a better way, you can inject the content via javascript with something like this:
NSString *injectSrc = #"var i = document.createElement('div'); i.innerHTML = '%#';document.documentElement.appendChild(i);";
NSString *runToInject = [NSString stringWithFormat:injectSrc, #"Hello World"];
[myWebView stringByEvaluatingJavascriptFromString:runToInject];
I'd recommend cleaning this up a bit, as it's not totally secure, but it should get the idea across of using javascript to inject new elements onto the page.