I'm trying to make a log in system for the app I am developing for a class project. This log in button would display on the navigation bar of most views so I was thinking of a separate class to initialize in the various view controllers to create the UIAlertView and handle the app to server communication. The issue I'm having is changing the Log In text to Log Out after the username and password has been checked and saved. I have been able to show the UIAlertView and talk with the server but am stuck on changing the text. I initially put a method in the view controller to change the text, with no success, but within the user file would be preferable. It is my first time using a singleton so I'm not interely sure on the correctness. Am I going about this the wrong way, is there a better way? Thanks for any help.
HomeViewController.m
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
self.navigationController.navigationBar.topItem.title = #"Home";
UIBarButtonItem *login = [[UIBarButtonItem alloc] initWithTitle:#"Log In" style:UIBarButtonItemStylePlain target:self action:#selector(log)];
self.navigationController.navigationBar.topItem.rightBarButtonItem = login;
}
-(void)log {
User* singleton = [User getInstance];
[singleton sign];
}
/*
-(void)logfinish {
if ([[NSUserDefaults standardUserDefaults] stringForKey:#"Username"] && [[NSUserDefaults standardUserDefaults] stringForKey:#"Password"]) {
UIBarButtonItem *logout = [[UIBarButtonItem alloc] initWithTitle:#"Log Out" style:UIBarButtonItemStylePlain target:self action:nil];
self.navigationController.navigationBar.topItem.rightBarButtonItem = logout;
}
}*/
User.m
#implementation User
static User *singletonInstance;
+ (User*)getInstance{
if (singletonInstance == nil) {
singletonInstance = [[super alloc] init];
}
return singletonInstance;
}
-(void)sign {
if (![[NSUserDefaults standardUserDefaults] stringForKey:#"Username"] && ![[NSUserDefaults standardUserDefaults] stringForKey:#"Password"]) {
signAlert = [[UIAlertView alloc] initWithTitle:#"Log In" message:#"Please sign into your account" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log In", nil];
signAlert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[signAlert show];
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *person = [signAlert textFieldAtIndex:0].text;
NSString *pass = [signAlert textFieldAtIndex:1].text;
NSDictionary *params = # {#"User": person, #"Password" :pass};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:signIn parameters:params success:^(AFHTTPRequestOperation *operation, NSData* response) {
NSString *responsef = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
//NSLog(#"%#", responsef);
[self check:responsef user:params];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
-(void)check:(NSString*) pass user:(NSDictionary*)nandp {
if ([pass isEqualToString:#"Success"]) {
[[NSUserDefaults standardUserDefaults] setValue:[nandp objectForKey:#"User"] forKey:#"Username"];
[[NSUserDefaults standardUserDefaults] setValue:[nandp objectForKey:#"Password"] forKey:#"Password"];
//NSLog(#"%# logged in", [[NSUserDefaults standardUserDefaults] stringForKey:#"Username"]);
//HomeViewController *view = [[HomeViewController alloc] init];
//[view logfinish];
}
else NSLog(#"Failure");
}
This is just one way of doing it.
Declare an instance variable like:
#implementation User {
UIViewController *viewController;
}
Pass the viewController you are calling from as a parameter to the method sign such as:
-(void)sign:(UIViewController *)viewControllerParam {
if (![[NSUserDefaults standardUserDefaults] stringForKey:#"Username"] && ![[NSUserDefaults standardUserDefaults] stringForKey:#"Password"]) {
signAlert = [[UIAlertView alloc] initWithTitle:#"Log In" message:#"Please sign into your account" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log In", nil];
signAlert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
viewController = viewControllerParam; // assigning to ivar for future use
[signAlert show];
}
}
Save this param to your instance variable for future reference. Now you can use this variable for calling a method in your viewController which changes the right bar button item:
-(void)check:(NSString*) pass user:(NSDictionary*)nandp {
if ([pass isEqualToString:#"Success"]) {
[[NSUserDefaults standardUserDefaults] setValue:[nandp objectForKey:#"User"] forKey:#"Username"];
[[NSUserDefaults standardUserDefaults] setValue:[nandp objectForKey:#"Password"] forKey:#"Password"];
[viewController logfinish]; // call the respective method
}
else NSLog(#"Failure");
}
Hope this helps! :)
Related
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"username"] == nil)
{
//Load Login View if no username is found
NSLog(#"No username found");
self.nameLoginView=[[NewLoginViewController alloc]initWithNibName:#"NewLoginViewController" bundle:nil];
[self.navigationController pushViewController:self.nameLoginView animated:YES];
}
else
{
NSString *savedUsername = [defaults stringForKey:#"username"];
NSLog(#"Username found: %#", savedUsername);
self.mainView = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
[self.navigationController pushViewController:self.mainView animated:YES];
}
I mean if he is logging for first time in our app he has to go to newLoginView Controller and if user is logging for second time he has to go to another view controller? i am doing this code in view controller itself?
Hope i am getting right your problem, you have problem to find that user is saved in your user Default or new user please have a look of below link:Click here to find solution
Hope this will be help full for you.
NSString *userName = [[NSString alloc] init];
NSString *userPass = [[NSString alloc] init];
userName = [[NSUserDefaults standardUserDefaults] objectForKey:#"username"];
userPass = [[NSUserDefaults standardUserDefaults] objectForKey:#"password"];
if([userName isEqualToString:name.text] && [userPass isEqualToString:passcode.text])
{
authgrantflag=1;
}
// Compare entered combo with configurator stored values ---Offline Authentication //
NSLog(#"Authentication flag=%d",authgrantflag);
if(authgrantflag==1)
{
// Local authentication successfull call home page//
NSLog(#"Local authentication success");
[pop1 dismissPopoverAnimated:YES];
HomeScreen *dcrmainpage=[[[HomeScreen alloc] initWithNibName:nil bundle:nil]autorelease];
[self presentViewController:dcrmainpage animated:YES completion:nil];
}
else
{
HomeScreen1 *dcrmainpage=[[[HomeScreen1 alloc] initWithNibName:nil bundle:nil]autorelease];
[self presentViewController:dcrmainpage animated:YES completion:nil];
}
So I am using Parse to link a user with their twitter account. In the app delegate I have the following:
[PFTwitterUtils initializeWithConsumerKey:CONSUMER_KEY consumerSecret:CONSUMER_SECRET];
Then the button which the user clicks to link the user to facebook calls the following:
-(IBAction)twitterConnectPressed{
NSLog(#"twitter");
[PFTwitterUtils linkUser:[PFUser currentUser] block:^(BOOL succeeded, NSError* error){
NSLog(#"haha");
if(succeeded){
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Done!" message:#"Connected with Twitter!" delegate:self cancelButtonTitle:#"okay" otherButtonTitles: nil];
[alert show];
self.fbButton.backgroundColor = [TGAPublic grey];
}else{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Oops" message:error.userInfo[#"error"] delegate:self cancelButtonTitle:#"okay" otherButtonTitles: nil];
[alert show];
}
}];
}
However even though linkUser:block: is called it doesn't do anything at all. It doesn't create a pop up to log in to twitter like [PFFacebookUtils linkUser:] does and therefore doesn't end up calling the block either
PFTwitterUtils does not appear to handle all cases on iOS. In particular, if you do not have an account setup (Settings->Twitter) it does not fire up a web view and attempt to used web oauth. Conversely if you have multiple Twitter accounts configured (again in Settings) then it doesn't appear to fire up an action sheet to allow you to select which account you'd like to link.
There's a great tutorial on how to do these things which exposes an extension to PFFacebookUtils here: http://natashatherobot.com/ios-twitter-login-parse/
It does not do linking though, just login, but should be a good basis to add linking.
I've got similar problem with link/unlink methods for both PFFacebookUtils and PFTwitterUtils (v. 1.7.4).
The only way I managed to make it work was to replace them by, unfortunately, messing with internal Parse implementation of authData:
#import "TwitterAuthProvider.h"
#import "PFTwitterUtils.h"
#import "PFUser.h"
static NSString * const kTwitterKey = #"XXX";
static NSString * const kTwitterSecret = #"XXX";
#implementation TwitterAuthProvider
- (instancetype)init {
if ((self = [super init])) {
[PFTwitterUtils initializeWithConsumerKey:kTwitterKey consumerSecret:kTwitterSecret];
}
return self;
}
- (void)setAuthData:(id)twAuthData forUser:(PFUser *)user {
static NSString * const kParseAuthDataKey = #"authData";
static NSString * const kParseLinkedServiceNamesKey = #"linkedServiceNames";
static NSString * const kParseAuthProviderName = #"twitter";
NSMutableDictionary *authData = [[user valueForKey:kParseAuthDataKey] mutableCopy] ?: [NSMutableDictionary dictionary];
authData[kParseAuthProviderName] = twAuthData ?: [NSNull null];
[user setObject:authData forKey:kParseAuthDataKey];
[user setValue:authData forKey:kParseAuthDataKey];
NSMutableSet *linkedServices = [[user valueForKey:kParseLinkedServiceNamesKey] mutableCopy] ?: [NSMutableSet set];
if (twAuthData) {
[linkedServices addObject:kParseAuthProviderName];
} else {
[linkedServices removeObject:kParseAuthProviderName];
}
[user setValue:linkedServices forKey:kParseLinkedServiceNamesKey];
}
- (void)linkWithCompletion:(PFBooleanResultBlock)completion {
NSParameterAssert(completion != nil);
PFUser *user = [PFUser currentUser];
__weak typeof(self) weakSelf = self;
PF_Twitter *twitter = [PFTwitterUtils twitter];
[twitter authorizeWithSuccess:^(void) {
[weakSelf setAuthData:[self twitterAuthData] forUser:user];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
//revert
[weakSelf setAuthData:nil forUser:user];
}
completion(succeeded, error);
}];
} failure:^(NSError *error) {
completion(NO, error);
} cancel:^(void) {
completion(NO, nil);
}];
}
- (void)unlinkWithCompletion:(PFBooleanResultBlock)completion {
NSParameterAssert(completion != nil);
PFUser *user = [PFUser currentUser];
[self setAuthData:nil forUser:user];
[user saveInBackgroundWithBlock:completion];
}
- (NSDictionary *)twitterAuthData {
PF_Twitter *twitter = [PFTwitterUtils twitter];
return #{
#"auth_token" : twitter.authToken,
#"auth_token_secret": twitter.authTokenSecret,
#"consumer_key": kTwitterKey,
#"consumer_secret": kTwitterSecret,
#"id": twitter.userId,
#"screen_name": twitter.screenName,
};
}
#end
i have an ios app which uses a login page and after authenticating it enters into the inbox page.But after entering the inbox page it comes back automatically to the login page
Login.m
{
if ([username length] == 0 || [password length] == 0)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"Make sure you enter a username and password!"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else
{
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Login_Info WHERE username='%#'",username]; // Execute the query.
NSLog(#" query = %#", query );
// Get the results.
if (self.arrLogin_Info != nil) {
self.arrLogin_Info = nil;
}
self.arrLogin_Info = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
[def setObject:[self.arrLogin_Info objectAtIndex:0] forKey:#"idKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:1] forKey:#"usernameKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:2] forKey:#"passwordKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:3] forKey:#"emailKey"];
NSLog(#" query output = %#", self.arrLogin_Info);
NSString *val = [self.arrLogin_Info objectAtIndex:2];
// NSLog(#" val = %#",val);
if ([val isEqualToString:password] )
{
// NSLog(#" Inside if before entering app");
[self.navigationController popToRootViewControllerAnimated:YES];
}
else
{
//NSLog(#" Inside else before entering app");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sorry!"
message:#"Please ensure you have entered the correct password!"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
}
#end
Inbox.m
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
id u = [def objectForKey:#"idkey"];
if(u)
{
NSString *query = [NSString stringWithFormat:#"Select *from Messages where recipient_ID=%#",u];
self.msg = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
// [self.tableView reloadData];
}
else
{
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
// [self.tableView reloadData];
}
- (IBAction)logout:(id)sender {
//[PFUser logOut];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"showLogin" ])
{
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
}
Your Inbox view controller uses the presence of an object for the key 'idkey' in NSUserDefaults to determine whether the user is already logged in, or whether to show the login screen.
I presume that this line in login.m
[def setObject:[self.arrLogin_Info objectAtIndex:0] forKey:#"idKey"];
is supposed to be setting that key, but you don't show where you initialise def - so my guess is that this is nil and you aren't saving the data in NSUserDefaults.
Also, all of this -
if (self.arrLogin_Info != nil) {
self.arrLogin_Info = nil;
}
self.arrLogin_Info = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
can be simplified to this
self.arrLogin_Info = [self.dbManager loadDataFromDB:query];
I have my iOS app working fine till now but today I faced the problem "We were unable to find the authorization token." which is happening sometimes(most of the time it is working fine).Strangely when I tried to login my LinkedIn account on my desktop I faced the same issue for the first time.I have been implementing same code in many apps but all were working fine.But today I got this issue in my new app.
Code Snippet:
Request Token:
- (void)requestTokenFromProvider
{
LOAMutableURLRequest *request =
[[[LOAMutableURLRequest alloc] initWithURL:requestTokenURL
consumer:self.consumer
token:nil
callback:linkedInCallbackURL
signatureProvider:nil] autorelease];
[request setHTTPMethod:#"POST"];
LOARequestParameter *nameParam = [[LOARequestParameter alloc] initWithName:#"scope" value:#"r_fullprofile+w_messages+r_network+r_emailaddress+rw_nus"];
NSArray *params = [NSArray arrayWithObjects:nameParam, nil];
[request setParameters:params];
LOARequestParameter * scopeParameter=[LOARequestParameter requestParameter:#"scope" value:#"r_fullprofile w_messages r_network r_emailaddress rw_nus"];
[request setParameters:[NSArray arrayWithObject:scopeParameter]];
LOADataFetcher *fetcher = [[[LOADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:#selector(requestTokenResult:didFinish:)
didFailSelector:#selector(requestTokenResult:didFail:)];
}
- (void)requestTokenResult:(LOAServiceTicket *)ticket didFinish:(NSData *)data
{
if (ticket.didSucceed == NO)
return;
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
self.requestToken = [[LOAToken alloc] initWithHTTPResponseBody:responseBody];
[responseBody release];
[self allowUserToLogin];
}
- (void)requestTokenResult:(LOAServiceTicket *)ticket didFail:(NSData *)error
{
NSLog(#"%#",[error description]);
}
Linkedin Login Page And Access Token:
- (void)allowUserToLogin
{
NSString *userLoginURLWithToken = [NSString stringWithFormat:#"%#?oauth_token=%#",
userLoginURLString, self.requestToken.key];
userLoginURL = [NSURL URLWithString:userLoginURLWithToken];
NSURLRequest *request = [NSMutableURLRequest requestWithURL: userLoginURL];
[webView loadRequest:request];
}
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
addressBar.text = urlString;
[activityIndicator startAnimating];
BOOL requestForCallbackURL = ([urlString rangeOfString:linkedInCallbackURL].location != NSNotFound);
if ( requestForCallbackURL )
{
BOOL userAllowedAccess = ([urlString rangeOfString:#"user_refused"].location == NSNotFound);
if ( userAllowedAccess )
{
[self.requestToken setVerifierWithUrl:url];
[self accessTokenFromProvider];
}
else
{
// User refused to allow our app access
// Notify parent and close this view
// [[NSNotificationCenter defaultCenter]
// postNotificationName:#"loginViewDidFinish"
// object:self
// userInfo:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"LinkedInCancelled"];
[[ImpActivityAgent defaultAgent] makeBusy:NO];
[self dismissViewControllerAnimated:NO completion:nil];
}
}
else
{
// Case (a) or (b), so ignore it
}
return YES;
}
- (void)accessTokenFromProvider
{
[[NSUserDefaults standardUserDefaults] setObject:self.consumer forKey:#"LinkedinConsumer"];
LOAMutableURLRequest *request =
[[[LOAMutableURLRequest alloc] initWithURL:accessTokenURL
consumer:self.consumer
token:self.requestToken
callback:nil
signatureProvider:nil] autorelease];
[request setHTTPMethod:#"POST"];
LOADataFetcher *fetcher = [[[LOADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:#selector(accessTokenResult:didFinish:)
didFailSelector:#selector(accessTokenResult:didFail:)];
}
- (void)accessTokenResult:(LOAServiceTicket *)ticket didFinish:(NSData *)data
{
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
[[NSUserDefaults standardUserDefaults] setObject:responseBody forKey:#"AccessTokenresponseBody"];
BOOL problem = ([responseBody rangeOfString:#"oauth_problem"].location != NSNotFound);
if ( problem )
{
NSLog(#"%#",responseBody);
}
else
{
self.accessToken = [[LOAToken alloc] initWithHTTPResponseBody:responseBody];
[[NSUserDefaults standardUserDefaults] setObject:responseBody forKey:#"accessToken"];//save here
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:#"TokenRefreshDate"];//save here
[[NSUserDefaults standardUserDefaults] synchronize];
}
// Notify parent and close this view
[[NSNotificationCenter defaultCenter]
postNotificationName:#"loginViewDidFinish"
object:self];
[self dismissViewControllerAnimated:NO completion:nil];
[responseBody release];
}
Request Urls:
- (void)initLinkedInApi
{
apikey = #"vwu3pmtjaxyz";
secretkey = #"XkPxP1DNANMg0Dzq";
self.consumer = [[LOAConsumer alloc] initWithKey:apikey
secret:secretkey
realm:#"http://api.linkedin.com/"];
requestTokenURLString = #"https://api.linkedin.com/uas/oauth/requestToken";
accessTokenURLString = #"https://api.linkedin.com/uas/oauth/accessToken";
userLoginURLString = #"https://www.linkedin.com/uas/oauth/authorize";
linkedInCallbackURL = #"hdlinked://linkedin/oauth";
requestTokenURL = [[NSURL URLWithString:requestTokenURLString] retain];
accessTokenURL = [[NSURL URLWithString:accessTokenURLString] retain];
userLoginURL = [[NSURL URLWithString:userLoginURLString] retain];
}
Can somebody please tell me what can be reason behind it?
I have posted this question to LinkedIn forum too where I got the response that there was some issue from their side as other other developers have also reported them the issue.
As per Kamyar Mohager LinkedIn Employee
Is this happening when you're authorizing a new user or are you trying to make calls with existing access tokens? Based on that error message, my assumption is that you're taking users through the auth flow and seeing the error message upon redirect to LinkedIn.com. Please confirm. We're looking into this issue as other developers have reported it.
Then only the following comment he has assured that the problem is resolved.
He Said:
Our team has resolved the "We were unable to find the authorization token" issue when redirecting users through the auth flow. Please let me know if any of you continue to experience this issue.
After hours of searching on google I still cant find a single topic about this one:
1. I need to put error handling functions if the user does not have internet connection.
2. the user have internet connection but cant connect to the server .
And where can I put these? I tried one topic but it don't show the alert view message.
Here is my code:
- (IBAction)getDataPressed
{
if([myRequest_ isExecuting])
{
return;
}
if(myRequest_ != nil)
{
[myRequest_ release];
}
myRequest_ = [[ASIHTTPRequest alloc]initWithURL:[NSURL URLWithString:URL_PATH]];
myRequest_.delegate = self;
[myRequest_ startAsynchronous];
}
#pragma ASI Delegate methods
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"Request finished successfully");
NSLog(#"%#",[request responseString]);
NSDictionary *responseDictionary = [[request responseString]JSONValue];
NSDictionary *arrayElement = [responseDictionary objectForKey:#"user"];
NSString *ID = [arrayElement valueForKeyPath:#"id"];
NSLog(#"id: %#",ID);
NSString *usr = [arrayElement valueForKeyPath:#"usr"];
NSLog(#"usr: %#",usr);
NSString *gd = [arrayElement valueForKeyPath:#"gd"];
NSLog(#"gd: %#",gd);
NSString *ag = [arrayElement valueForKeyPath:#"ag"];
NSLog(#"ag: %#",ag);
NSString *st = [arrayElement valueForKeyPath:#"st"];
NSLog(#"st: %#",st);
NSString *lf = [arrayElement valueForKeyPath:#"lf"];
NSLog(#"lf: %#",lf);
NSString *da = [arrayElement valueForKeyPath:#"da"];
NSLog(#"da: %d",da);
for(NSString *value in [arrayElement allValues]){
NSLog(#"Found Value %#",value);
label.text = [value stringByAppendingFormat:#",%#,%#,%#,%#,%#,%#,",ID,usr,gd,ag,st,lf];
}
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSLog(#"Error %#", [request error]);
if([request error])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Destination Unreachable" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
-(void) dealloc
{
[super dealloc];
}
Thanks to those who will help ^_^
I think you could try the Reachbility application to help you out checking if you have internet or not. As for the server itself, you can use the NSUrlConnection Delegate methods to check if there was a problem with your request (by seeing the kind of HTTP code that comes)