I am teaching myself how to program an iPhone app by looking at code examples from various sources online, so it is fair to say that I do not understand the language (yet).
I am have successfully built a UIWebView browser app that goes to a login page. However, I am trying to take it one step further by having the
Following Byron's code on his own stack overflow question, I have tried to follow in his footsteps.
Is it possible for a UIWebView to save and autofill previously entered form values (e.g., username & password)?
However, when the following line of code is live in the app, the browser will only load a blank page.
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; {
I really appreciate any assistance to help get me back on the right track. Thank you very much,
Below is my entire code:
#import "ViewController.h"
// 6/13/2012 added to cache username and password
#import
#import "SFHFKeychainUtils.h"
// -----
#interface ViewController ()
#end
#implementation ViewController
#synthesize webView;
#synthesize spinner;
-(IBAction)goBack:(id)sender{
if ([webView canGoBack]) {
[webView goBack];
}
}
-(IBAction)goForward:(id)sender{
if ([webView canGoForward]){
[webView goForward];
}
}
- (void)viewDidLoad
{
NSURL *url = [NSURL URLWithString:#"http://xxxxxx.com/weblink/hh_login.html"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
// 6/13/2012 added to cache username and password
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; {
//save form data
if(navigationType == UIWebViewNavigationTypeFormSubmitted) {
//grab the data from the page
NSString *username = [self.webView stringByEvaluatingJavaScriptFromString: #"document.myForm.username.value"];
NSString *password = [self.webView stringByEvaluatingJavaScriptFromString: #"document.myForm.password.value"];
//store values locally
[[NSUserDefaults standardUserDefaults] setObject:username forKey:#"username"];
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:#"MyService" updateExisting:YES error:nil];
}
}
// -----
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[spinner startAnimating];
}
//- (void)webViewDidFinishLoad:(UIWebView *)webView {
// [spinner stopAnimating];
//}
// 6/13/2012 added to cache username and password
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[spinner stopAnimating];
//verify view is on the login page of the site (simplified)
NSURL *requestURL = [self.webView.request URL];
if ([requestURL.host isEqualToString:#"http://xxxxxx.com/weblink/hh_login.html"]) {
//check for stored login credentials
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:#"username"];
if (username.length != 0 ) {
//create js strings
NSString *loadUsernameJS = [NSString stringWithFormat:#"document.myForm.username.value ='%#'", username];
NSString *password = [SFHFKeychainUtils getPasswordForUsername: username andServiceName:#"MyService" error:nil];
if (password.length == 0 ) password = #"";
NSString *loadPasswordJS = [NSString stringWithFormat:#"document.myForm.password.value ='%#'", password];
//autofill the form
[self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
[self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
}
}
}
// -----
#end
TRY BELOW ONE
You need to fill the credential when webview has loaded .
below is the delegate method of UIWebView called when the WebView has loaded.At this time pass the credential not as were passing before loading the UIWebView which is not correct.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if(!isLoggedIn){//just load only onetime.
//pass the login Credintails into textfield of WebView.
NSString* userId = #"userName" //here just replace that string to the username
NSString* password = #"password";//here just replace that string to the password
if(userId != nil && password != nil ){
NSString* jScriptString1 = [NSString stringWithFormat:#"document.getElementById('username').value='%#'", userId];
//username is the id for username field in Login form
NSString* jScriptString2 = [NSString stringWithFormat:#"document.getElementById('password').value='%#'", password];
//here password is the id for password field in Login Form
//Now Call The Javascript for entring these Credential in login Form
[webView stringByEvaluatingJavaScriptFromString:jScriptString1];
[webView stringByEvaluatingJavaScriptFromString:jScriptString2];
//Further if you want to submit login Form Automatically the you may use below line
[webView stringByEvaluatingJavaScriptFromString:#"document.forms['login_form'].submit();"];
// here 'login_form' is the id name of LoginForm
}
isLoggedIn=TRUE;
}
}
It'll really help you.
Related
I am receiving a description text in HTML format, and I am loading it in a webview, if a link clicked in the description so I load it in separate view controller. But shouldStartLoadWithRequest giving a some appended link. here is my code
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if(navigationType == UIWebViewNavigationTypeLinkClicked) {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
WebsiteViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"WebsiteViewController"];
vc.url = request.URL.absoluteString;
NSLog(#"link is : %#", [[request URL] absoluteString]);
[self.navigationController pushViewController:vc animated:YES];
return false;
}
return true;
}
it prints this
link is : applewebdata://038EEEBF-A4C9-4C7D-8FB5-32056714B855/www.yahoo.com
and I am loading it like this
[webViewDescription loadHTMLString:description baseURL:nil];
As you are using loadHTMLString and you are setting baseURL to nil therefore applewebdata URI scheme is used by iOS instead of the “http” in URIs used for accessing internal resources on the device. You could try setting the baseURL
I had a similar issue. In practice, setting the baseURL to 'http://' or something like that wasn't working for me either. I also only saw the applewebdata scheme about 50% of the time, the other 50% of the time I saw the correct scheme I was expecting.
To resolve this, I ended up intercepting -webView:shouldStartLoadWithRequest:navigationType: callbacks and using a regular expression to strip out Apple's applewebdata scheme. Here's what it ended up looking like
// Scheme used to intercept UIWebView callbacks
static NSString *bridgeScheme = #"myCoolScheme";
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
BOOL shouldStartLoad = YES;
NSURL *requestURL = request.URL;
// Strip out applewebdata://<UUID> prefix applied when HTML is loaded locally
if ([requestURL.scheme isEqualToString:#"applewebdata"]) {
NSString *requestURLString = requestURL.absoluteString;
NSString *trimmedRequestURLString = [requestURLString stringByReplacingOccurrencesOfString:#"^(?:applewebdata://[0-9A-Z-]*/?)" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, requestURLString.length)];
if (trimmedRequestURLString.length > 0) {
requestURL = [NSURL URLWithString:trimmedRequestURLString];
}
}
if ([requestURL.scheme isEqualToString:bridgeScheme]) {
// Do your thing
shouldStartLoad = NO;
}
return shouldStartLoad;
}
I am integrating Linked-in in my iOS application to Login my app.it works fine for me ..it login successfully when i enter the credentials in the app and enters in the app successfully ....but when i logout and login again it ask for the Access-->allow access button without asking the credientials but I want allow access page should not come on the next login ...means after logout when again i click on the linkedin``login...it should directly access to the app ..should not ask for image 2..
image 2 which comes on the second time login..which i dont want to come
.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSMutableArray *toolbarButtons = [toolBar.items mutableCopy];
// toolbarItems = [[NSMutableArray arrayWithArray:toolbar.items]
// This is how you remove the button from the toolbar and animate it
// This is how you add the button to the toolbar and animate it
if (!firstTime1||![loginView canGoBack])
{
[toolbarButtons removeObject:backButton];
[toolBar setItems:toolbarButtons animated:YES];
firstTime1=YES;
}
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
BOOL requestForCallbackURL = ([urlString rangeOfString:[LinkedIn linked].linkedInCallbackURL].location != NSNotFound);
if ( requestForCallbackURL )
{
BOOL userAllowedAccess = ([urlString rangeOfString:#"user_refused"].location == NSNotFound);
if ( userAllowedAccess )
{
if ([self logoutPreviousSession])
{
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"SuccessfulLogin"];
[DelegateClass magazine]._loggedThrough=#"LinkedIn";
[[LinkedIn linked].requestToken setVerifierWithUrl:url];
[[LinkedIn linked] accessTokenFromProvider];
}
}
else
{
[self dismissModalViewControllerAnimated:YES];
}
}
return YES;
}
guys. I'm trying to realize opening link from my webView in safari. Sometimes it works perfect, sometimes showing exc bad access.
This is my code:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
urlWillShow = [request mainDocumentURL];
return YES;
}
- (IBAction)openInSafari {
NSLog(#"Will try to open in safari link: %#", [urlWillShow absoluteString]);
if ([[urlWillShow scheme] isEqualToString:#"http"] || [[urlWillShow scheme] isEqualToString:#"https"]) {
BOOL canLoad = [[UIApplication sharedApplication] canOpenURL:urlWillShow];
if (canLoad == YES) {
[[UIApplication sharedApplication] openURL:urlWillShow];
}
}
}
Use [request URL] instead of [request mainDocumentURL]
Also, you need to retain (if not using ARC) urlWillShow as its likely being released before your action is called.
Alternatively, make the UIWebView an IBOutlet and instead of storing urlWillShow in an ivar, you can use [[self.webView request] URL] in your action method.
I have an app in the process of upgrading to the iOS5 SDK and Phonegap 1.0.0
The Childbrowser plugin is working properly, but when a link to the iTunes app store is clicked - the link is opened in a Childbrowser window.
I would prefer it to open in Appstore directly, which is what happens if I do not use the ChildBrowser plugin.
This is the appstore link (points to a submit a review page within the appstore)
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=386470812&pageNumber=0&sortOrdering=1&type=Purple+Software&mt=8
and this is how AppDelegate is modified
AppDelegate.m, scroll way down and replace the following:
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
}
with this:
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:
(NSURLRequest *)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if ([[url scheme] isEqualToString:#"gap"] || [url isFileURL]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
else {
ChildBrowserViewController* childBrowser =
[ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
[super.viewController presentModalViewController:childBrowser
animated:YES ];
[childBrowser loadURL:[url description]];
[childBrowser release];
return NO;
}
}
I used the method outlined in this blogpost to get the Childbrowser up and running
http://iphonedevlog.wordpress.com/2011/09/24/installing-childbrowser-into-xcode-4-with-phonegap-1-0-mac-os-x-snow-leopard/
Any thoughts on how to change this to produce the desired action?
Many thanks..
You need to check whether your URL contain http://itunes.apple.com/ as a substring by using rangeOfString: method and location attribute.
Please confirm your javascript called the url like this, window.location="http://itunes.apple.com/us/app/code-check-basic-free-medical/id386470812?mt=8"; or you can use any jquery method.
Please replace shouldStartLoadWithRequest: method with the following snippet.
/**
* Start Loading Request
* This is where most of the magic happens... We take the request(s) and process the response.
* From here we can re direct links and other protocalls to different internal methods.
*/
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:
(NSURLRequest *)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if ([[url scheme] isEqualToString:#"gap"] || [url isFileURL]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
else {
//here we will check whether urlString has http://itunes.apple.com/ as substring or not
NSString* urlString=[url absoluteString];
if ([urlString rangeOfString:#"http://itunes.apple.com/"].location == NSNotFound){
ChildBrowserViewController* childBrowser = [ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
childBrowser.modalPresentationStyle = UIModalPresentationFormSheet;
childBrowser.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[super.viewController presentModalViewController:childBrowser animated:YES ];
[childBrowser loadURL:urlString];
[childBrowser release];
return NO;
}
else
return YES;
}
}
thanks,
Mayur
Why doesn't this code work? It shows the Google screen but it doesn't change the text box value. I confirmed that the JS does work by running it in Safari, and this code seems to work otherwise since running alert('hi') does work.
NSURL *web_url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *web_request = [NSURLRequest requestWithURL:web_url];
[web_screen loadRequest:web_request];
NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
Just expanding on the previous answer. You need to conform to the UIWebViewDelegate protocol by setting the delegate property of the UIWebView like this:
web_screen.delegate = self;
Then you can implement one of the delegate methods to know when a request has finished loading and is therefore ready to have scripts run like so:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
}
For more information on the UIWebViewDelegate protocol visit the Apple site http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html
The Load URL action takes place asynchronously. It does not even start until your method has ended. So your javascript is being pushed into an empty UIWebView, then your method ends, then the load happens.
You need to let your method end before the js is pushed in. The standard approach for this is to use a Delegate object, which will have a method called on it when the load completes. Only then does it make sense to push in the javascript.
Does it work if you wait for the page to finish loading first?
Consider looking at NSURLConnection and its delegate methods. You can use these to check on the status of a download.
#interface
...
NSURLConnection *connectionInProgress;
NSData *googleRequestResponseData;
NSURL *googleURL;
...
#implementation
...
- (void) setUpRequest {
googleURL = [[NSURL URLWithString:#"http://www.google.com/"] retain];
googleRequestResponseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
#pragma mark NSURLConnection delegate methods
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[googleRequestResponseData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[web_screen loadData:googleRequestResponseData MIMEType:#"application/octet-stream" textEncodingName:#"utf-8" baseURL:googleURL];
NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test';"];
NSLog (js_result);
[googleURL release];
[googleRequestResponseData release];
[connectionInProgress release];
connectionInProgress = nil;
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog (#"Connection failed to load data from Google!");
[googleURL release];
[googleRequestResponseData release];
[connectionInProgress release];
connectionInProgress = nil;
}
Alternatively, check out Ben Copsey's ASIHTTPRequest wrapper, which includes a simplified approach to asynchronous downloads (see ASINetworkQueue, specifically).
You can use ASINetworkQueue to run a method of your choice (to run the Javascript code, for example), once the request download is complete.
add '.innerHTML' after what you are searching for
In your case do the following
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('input')[1].value='test'.innerHTML"];
}
This worked for me .
check this for more info here