I'm working on an iOS app for my school that will allow the user to access school documents like schedules, calendars, and grade/tuition sites. I've been doing research on how to save credentials for some of the sites that require logins, and my ultimate goal is not only save credentials, but automatically log in the user to the websites when the webview is loaded as well. So far my code looks like this:
#import "PJP Webview.h"
#implementation PJP_Webview
#synthesize webView, loginView, username, password, body, urlToLink,usernameField,passwordField, firstTime, loginNeeded, callerCell;
-(void) viewDidLoad {
[super viewDidLoad];
loginView.hidden = true;
if (firstTime && loginNeeded) {
loginView.hidden = false;
[self.view bringSubviewToFront:loginView];
}
else {
loginView.hidden = true;
[self.view addSubview:self.webView];
[self.view bringSubviewToFront:webView];
if (loginNeeded) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *usernameSave = [NSString stringWithFormat:#"%#username", self.callerCell];
self.username = [userDefaults objectForKey:usernameSave];
NSString *passwordSave = [NSString stringWithFormat:#"%#password", self.callerCell];
self.password = [userDefaults objectForKey:passwordSave];
NSURL *url = [NSURL URLWithString: urlToLink];
NSString *bodyForUse = [NSString stringWithFormat: body, username, password];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
[request setHTTPMethod: #"POST"];
[request setHTTPBody: [bodyForUse dataUsingEncoding: NSUTF8StringEncoding]];
[webView loadRequest: request];
}
else {
NSURL *url = [NSURL URLWithString: urlToLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
}
}
- (IBAction)acceptInput:(id)sender {
self.username = usernameField.text;
self.password = passwordField.text;
loginView.hidden = true;
[self.view addSubview:self.webView];
[self.view bringSubviewToFront:webView];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *usernameSave = [NSString stringWithFormat:#"%#username", self.callerCell];
[userDefaults setObject:username forKey:usernameSave];
NSString *passwordSave = [NSString stringWithFormat:#"%#password", self.callerCell];
[userDefaults setObject:password forKey:passwordSave];
[userDefaults synchronize];
NSURL *url = [NSURL URLWithString: urlToLink];
NSString *bodyForUse = [NSString stringWithFormat: body, username, password];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
[request setHTTPMethod: #"POST"];
[request setHTTPBody: [bodyForUse dataUsingEncoding: NSUTF8StringEncoding]];
[webView loadRequest: request];
}
#end
I modeled some of my code after another stack overflow article found here Loading a webpage through UIWebView with POST parameters
An example of one of the websites I am trying to integrate is https://adphila.gradeconnect.com/front/slogin.php
So far my code has not been successful at logging me into the website and taking me to the next page, so I'm not sure if maybe the body I am using for the parameters is wrong, if my code is faulty, or some other issue is present. Also, if you have any suggestions for how to make my previous code more efficient I welcome that too!
Edit: The school also uses gmail for student emails, so is it possible to embed a uiwebview of email content as well? I know Google has their own APIs but I have never used non-Apple libraries before.
Edit 2:
#import "PJP Webview.h"
#implementation PJP_Webview
#synthesize webViewCurrent, loginView, username, password, bodyUsername, bodyPassword, urlToLink,usernameField,passwordField, firstTime, loginNeeded, callerCell, bodyButton;
-(void) viewDidLoad {
[super viewDidLoad];
[webViewCurrent setDelegate:self];
loginView.hidden = true;
if (firstTime && loginNeeded) {
loginView.hidden = false;
[self.view bringSubviewToFront:loginView];
}
else {
loginView.hidden = true;
if (loginNeeded) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *usernameSave = [NSString stringWithFormat:#"%#username", self.callerCell];
self.username = [userDefaults objectForKey:usernameSave];
NSString *passwordSave = [NSString stringWithFormat:#"%#password", self.callerCell];
self.password = [userDefaults objectForKey:passwordSave];
NSURL *url = [NSURL URLWithString: urlToLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webViewCurrent loadRequest:request];
}
else {
NSURL *url = [NSURL URLWithString: urlToLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webViewCurrent loadRequest:request];
}
[self.view addSubview:self.webViewCurrent];
[self.view bringSubviewToFront:webViewCurrent];
}
}
- (IBAction)acceptInput:(id)sender {
self.username = usernameField.text;
self.password = passwordField.text;
loginView.hidden = true;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *usernameSave = [NSString stringWithFormat:#"%#username", self.callerCell];
[userDefaults setObject:username forKey:usernameSave];
NSString *passwordSave = [NSString stringWithFormat:#"%#password", self.callerCell];
[userDefaults setObject:password forKey:passwordSave];
[userDefaults synchronize];
NSURL *url = [NSURL URLWithString: urlToLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webViewCurrent loadRequest:request];
[self.view addSubview:self.webViewCurrent];
[self.view bringSubviewToFront:webViewCurrent];
}
-(void) webViewDidFinishLoad:(UIWebView *)webView {
NSString *fillData = [NSString stringWithFormat:#"document.getElementById('%#').value = '%#';document.getElementById('%#').value = '%#';", bodyUsername, username, bodyPassword, password];
[webView stringByEvaluatingJavaScriptFromString:fillData];
NSString *buttonData = [NSString stringWithFormat:#"document.getElementById('%#').click()", bodyButton];
[webView stringByEvaluatingJavaScriptFromString:buttonData];
}
#end
There is a new error though, void SendDelegateMessage(NSInvocation *): delegate (webView:didFinishLoadForFrame:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
For the website I am using, the bodyUsername is lusername, the bodyPassword lpassword, and the bodyButton login. The page loads but is not executing the javascript.
You can do this by Autopopulating the username and password field of that webpage. First get the name of the username and password field from the webpage. right click on the webpage.
Click on inspect element and then You van easily find it.
Then write the WebView Delegate Method.
// ViewController.m
// WebDemo
//
// Created by Nilesh on 7/31/16.
// Copyright © 2016 Nilesh. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()<UIWebViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *urlToLink = #"https://adphila.gradeconnect.com/front/slogin.php";
NSURL *url = [NSURL URLWithString: urlToLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) webViewDidFinishLoad:(UIWebView *)webView {
NSString* userId = #"userName" ;//Your userName
NSString* password = #"password";// Your Password
NSString* jScriptString1 = [NSString stringWithFormat:#"document.forms[0]['lusername'].value='%#'", userId];
NSString* jScriptString2 = [NSString stringWithFormat:#"document.forms[0]['lpassword'].value='%#'", password];
[webView stringByEvaluatingJavaScriptFromString:jScriptString1];
[webView stringByEvaluatingJavaScriptFromString:jScriptString2];
NSString *jsStat = #"document.forms[0]['login'].click()";
[webView stringByEvaluatingJavaScriptFromString:jsStat];
}
#end
Related
I would like to retrieve the data from a specific part of the html of a site, and I wrote the following code. Unfortunately, the code is not working. How can I fix this?
the html class name is "topic_content", and every article in applicable site contains it (see the comments in code).
#implementation DetailViewController
....
UIActivityIndicatorView *activityIndicator;
- (void)viewDidLoad {
.....
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[activityIndicator stopAnimating];
....
[self callDetailNews];
}
-(void)callDetailNews{
....
if ([[Reachability reachabilityForInternetConnection]currentReachabilityStatus]!=NotReachable)
{
// article link :: http://el3en.com/?articles=topic&topic=20840 (token_ID)
// <td class="topic_content" colspan='6' itemprop="articleBody" style="text-align:justify; word-wrap: break-word; width:100%">
// NSString *someHTML = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('box')[0].innerHTML;"];
NSString *articleString = [NSString stringWithFormat:#"http://el3en.com/?articles=topic&topic=%#",token_ID];
NSURL *articleURL = [NSURL URLWithString:articleString];
NSError *error;
NSString *articlePage = [NSString stringWithContentsOfURL:articleURL
encoding:NSASCIIStringEncoding
error:&error];
[_webView loadHTMLString:articlePage baseURL:nil];
//NSString *someHTML = [_webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('topic_content')[0].innerHTML;"];
//NSLog(#"Content : %#",someHTML);
}
.....
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[activityIndicator startAnimating];
self.webView.hidden=true;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self.webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('topic_content')[0].sinnerHTML;"];
[activityIndicator stopAnimating];
self.webView.hidden=false;
}
Thanks
You should use innerHtml instead sinnerHtml, besides this you need to get the string and load this string into another webview. Pls see example
#import "ViewController.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIWebView *fakeView;
#end
#implementation ViewController
UIActivityIndicatorView *activityIndicator;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[activityIndicator stopAnimating];
[self callDetailNews];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)callDetailNews{
if ([[Reachability reachabilityForInternetConnection]currentReachabilityStatus]!=NotReachable)
{
// article link :: http://el3en.com/?articles=topic&topic=20840 (token_ID)
// <td class="topic_content" colspan='6' itemprop="articleBody" style="text-align:justify; word-wrap: break-word; width:100%">
// NSString *someHTML = [webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('box')[0].innerHTML;"];
NSString *articleString = [NSString stringWithFormat:#"http://el3en.com/?articles=topic&topic=%#",#"20840"];
NSURL *articleURL = [NSURL URLWithString:articleString];
NSError *error;
NSString *articlePage = [NSString stringWithContentsOfURL:articleURL
encoding:NSASCIIStringEncoding
error:&error];
NSLog(#"Request %#",articleURL);
self.fakeView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
self.fakeView.delegate = self;
[self.fakeView loadRequest:[NSURLRequest requestWithURL:articleURL]];
//NSString *someHTML = [_webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('topic_content')[0].innerHTML;"];
//NSLog(#"Content : %#",someHTML);
}
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[activityIndicator startAnimating];
self.webView.hidden=true;
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(#"error %#" ,[error description]);
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if(webView == self.fakeView) {
NSString* javascriptString = [self.fakeView stringByEvaluatingJavaScriptFromString:#"document.getElementsByClassName('topic_content')[0].innerHTML"];
NSLog(#"%#",javascriptString);
[self.webView loadHTMLString:javascriptString baseURL:[NSURL URLWithString:#""]];
self.fakeView = nil;
}else{
[activityIndicator stopAnimating];
self.webView.hidden=false;
}
}
#end
I am a beginner in Obj-C and I try to make an app with this raywenderlich tutorial.
I parse html page with Title of articles (mininglife.ru) , also I getting an urls of each articles and keep it in an NSMutableArray for using it in my DetailviewController.
But when I try to pull urls off and put it in NSUrl nothing happens. I've tried a lot of ways, Can you help me with it and try to explain if I do something wrong. Thank you.
-(void)loadArticles{
Articlelist *urlOfArticle = [_objects objectAtIndex:self]; // from previous parsing
NSURL *articleUrl = [NSURL URLWithString:urlOfArticle.url];// I think this string is wrong, or?
NSData *htmlUrlsData = [NSData dataWithContentsOfURL:articleUrl];
TFHpple *articleParser = [TFHpple hppleWithHTMLData:htmlUrlsData];
NSString *articleNameXpath = #"/html/body/div[1]/div/div[1]/main/article/h1";
// NSString *articleContentXpath = #"//div[#class'entry-content']//p";
NSArray *articleNameNodes = [articleParser searchWithXPathQuery:articleNameXpath];
// NSArray *articleContentNodes = [articleParser searchWithXPathQuery:articleContentXpath];
NSMutableArray *newArticleArray = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in articleNameNodes) {
Article *newArticleName = [[Article alloc] init];
[newArticleArray addObject:newArticleName];
newArticleName.name = [[element firstChild] content];
}
_articleName = newArticleArray;
[self.tableView reloadData];
}
Change interface to this
#interface MasterViewController () {
NSMutableArray *_articles;
}
#end
Add this to MasterViewController
- (void)loadArticles
{
NSURL *articlesUrl = [NSURL URLWithString:#"http://mininglife.ru"];
NSData *articlesHtmlData = [NSData dataWithContentsOfURL:articlesUrl];
TFHpple *articlesParser = [TFHpple hppleWithHTMLData:articlesHtmlData];
NSString *articlesXpathQueryString = #"/html/body/div[1]/div/div[1]/main/article/h1";
NSArray *articlesNodes = [articlesParser searchWithXPathQuery:articlesXpathQueryString];
NSMutableArray *newArticles = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in articlesNodes) {
Article *article = [[Article alloc] init];
[newArticles addObject:article];
article.title = [[element firstChild] content];
article.url = [element objectForKey:#"href"];
}
_articles = newArticles;
[self.tableView reloadData];
}
Change DetailviewController.h's interface to
#class Article;
#interface DetailViewController : UIViewController
#property (strong, nonatomic) Article *article;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
Change DetailViewController.m to
#import "DetailViewController.h"
#import "Article.h"
#import "TFHpple.h"
#implementation DetailViewController
#synthesize detailDescriptionLabel = _detailDescriptionLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadArticle];
}
- (void)loadArticle
{
NSURL *articleUrl = [NSURL URLWithString:self.article.url];
NSData *articleHtmlData = [NSData dataWithContentsOfURL:articleUrl];
TFHpple *articleParser = [TFHpple hppleWithHTMLData:articleHtmlData];
NSString *articleXpathQueryString = #"//div[#class'entry-content']//p";
NSArray *articleNodes = [articleParser searchWithXPathQuery:articleXpathQueryString];
NSMutableArray *newArticleContents = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in articleNodes) {
[newArticleContents addObject:[[element firstChild] content]];
}
NSLog(#"%#", newArticleContents);
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Detail", #"Detail");
}
return self;
}
#end
Don't forget to change all call to loadTutorials to loadArticles in MasterViewController. PS: This example only prints the articles content to the console
Your xPath might be wrong as well
I am a beginner & I am trying to figure out how to upload text from a textfield to a server along with coordinates but I need to add the textfield to userdefaults.
The UITextfield is in my ViewController, while the coordinates & post to server are in a separate object class.
A tutorial or sample code will be very helpful.
Below, I have attached the relevant code I am using to upload the coordinates.
What I need is help on adding and uploading text from UITextfield in another class to the code below.
Singleton.m
#implementation Singleton {
CLLocation *location;
CLLocationManager *locationManager;
NSMutableData *responseData;
}
- (id)init {
if (self = [super init]) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setDouble:location.coordinate.latitude forKey:#"latitude"];
[userDefaults setDouble:location.coordinate.longitude forKey:#"longitude"];
[userDefaults synchronize];
}
return self;
}
- (void) timerDidFire:(NSTimer *)timer
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (([userDefaults doubleForKey:#"latitude"] != location.coordinate.latitude) || ([userDefaults doubleForKey:#"longtitude"] != location.coordinate.longitude)) {
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:#"http://setslocation.php"]];
NSDictionary *requestData = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSString stringWithFormat:#"%f", location.coordinate.longitude], #"longitude",
[NSString stringWithFormat:#"%f", location.coordinate.latitude], #"latitude",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:requestData options:0 error:&error];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
[NSURLConnection connectionWithRequest:request delegate:self];
[userDefaults setDouble:location.coordinate.latitude forKey:#"latitude"];
[userDefaults setDouble:location.coordinate.longitude forKey:#"longtitude"];
[userDefaults synchronize];
}
}
first save your textfield value to NSUserDefaults and synchronize. You can get your value any where in your project from NSUserDefaults.
set value like:
[[NSUserDefaults standardUserDefaults] setObject:#"your textfield value" forKey:#"your key name"];
[[NSUserDefaults standardUserDefaults] synchronize];
get value:
NSLog(#"%#",[[NSUserDefaults standardUserDefaults] objectForKey:#"your key name"]);
make sure you write same key name.
I'm trying to launch a UIViewController when a table line is clicked...
The code is main view controller is ...
- (void)showDetail:(NSString *)detail
{
DetailViewController *secondViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:secondViewController animated:YES];
[DetailViewController release];
}
I filled in the viewDidLoad method in my "DetailViewController" class that is attached to the NIB.
- (void)viewDidLoad:(BOOL)animated;
{
NSURL *url = [NSURL URLWithString:#"www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
When I hit the pushViewController method, the NIB appears to load (can see a test label on it) but the viewDidLoad method is not called. In that method, I'm trying to load a test HTML into a UIWebView.
Any ideas?
There is no event viewDidLoad: change to the bellow it should work.
- (void)viewDidLoad{
NSURL *url = [NSURL URLWithString:#"www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
I'm trying to display a local html file from a three20 table controller. The table shows up correctly, but when I select the item, all I get is a blank screen. If I use an external URL, the page shows correctly. I haven't tried using UIWebView, but I was wondering if there was an easy way using the Three20 framework.
Thanks.
EDIT: I forgot that has changed recently...
Assuming you have registered a TTWebController in your navigator that way :
TTNavigator* navigator = [TTNavigator navigator];
TTURLMap* map = navigator.URLMap;
[map from:#"*" toViewController:[TTWebController class]];
You can simply open a local html file that way :
NSString *creditsPath = [[NSBundle mainBundle] pathForResource:#"credits" ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:creditsPath];
TTOpenURL([url description]);
Then all you have to to is to add TTTableLinkedItem or subclass (almost all of TT*Cell are) to your dataSource with a local file URL like that :
NSString *creditsPath = [[NSBundle mainBundle] pathForResource:#"credits" ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:creditsPath];
TTTableTextItem *item = [TTTableTextItem itemWithText:#"foobar" URL:[url description]];
Much simpler that what I wrote before...
ENDOFEDIT
Forget whats under, unless you're interested in others solutions... (more complex... or not, see last one)
Basically here is how you load content in a UIWebView :
NSString *creditsPath = [[NSBundle mainBundle] pathForResource:#"credits" ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:creditsPath];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlRequest];
The three20 TTWebController can take a request in a query :
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
if (self = [self initWithNibName:nil bundle:nil]) {
NSURLRequest* request = [query objectForKey:#"request"];
if (nil != request) {
[self openRequest:request];
} else {
[self openURL:URL];
}
}
return self;
}
So to open a local html file in a TTWebController you could do this :
NSString *creditsPath = [[NSBundle mainBundle] pathForResource:#"credits" ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:creditsPath];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[[TTNavigator navigator] openURLAction:
[[[TTURLAction actionWithURLPath:#"url://to/your/ttwebcontroller"]
applyQuery:[NSDictionary dictionaryWithObject:ulrRequest
forKey:#"request"]]
applyAnimated:YES]];
Now the last part, to trigger this from a TTTableViewController...
You have in your ViewController to implement :
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath*)indexPath {
// there you retrieve a *TTTableItem* corresponding to your row
// and call previous snippet from URL...
// TTTableItem class has userInfo property you could use:
TTTableItem *item = (TTTableItem *)object;
NSString *htmlFile = item.userInfo.
[self openLocalHtmlFile:htmlFile];
}
Hope that helps!
Nothing tested, at all, should not compile or whatsoever, but that is a solution.
That's a solution using basic three20 + iOS features. You could also write a TTCustomWebController inheriting from TTWebController that would take urls like #"myapp://openLocalHtml?file=credits" that's not that hard to do...
...That here is a draft :
#interface TTCustomWebController : TTWebController {}
#end
#implementation TTCustomWebController
- (id)initWithFile:(NSString *)name {
self = [super init];
if (self) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:name ofType:#"html"];
NSURL *URL = [NSURL fileURLWithPath:filePath];
[self openURL:URL];
}
return self;
}
#end
Then you could simply use TTTableLinkedItem in your datasource pointing to these #"myapp://openLocalHtml?file=credits"...
Good luck! :)