I am recieving an error on this line in my ViewControllerLogin.m file or anywhere a UIAlert shows up...
[UIAlertView error:#"Enter username and password over 4 chars each."];
The above code gives me an error in the issues editor: "no known class for method selector". I identified the method 'error' in another class in Xcode. Does anyone know why I am getting this error?
UPDATE ViewControllerLogin.m (the UIViewAlets are at the bottom)
#import "ViewControllerLogin.h"
#import "UIAlertView+error.h"
#import "API.h"
#include <CommonCrypto/CommonDigest.h>
#define kSalt #"adlfu3489tyh2jnkLIUGI&%EV(&0982cbgrykxjnk8855"
#implementation ViewControllerLogin
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillDisappear:animated];
}
-(void)viewDidLoad {
[super viewDidLoad];
//focus on the username field / show keyboard
[fldUsername becomeFirstResponder];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"qwertygreen.png"] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.titleTextAttributes = #{NSForegroundColorAttributeName: [UIColor whiteColor]};
self.title = #"play";
//changes the buttn color
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
// Do any additional setup after loading the view.
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(IBAction)btnLoginRegisterTapped:(UIButton*)sender {
//form fields validation
if (fldUsername.text.length < 4 || fldPassword.text.length < 4)
{
[UIAlertView error:#"Enter username and password over 4 chars each."];
return;
}
//salt the password
NSString* saltedPassword = [NSString stringWithFormat:#"%#%#", fldPassword.text, kSalt];
//prepare the hashed storage
NSString* hashedPassword = nil;
unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
//hash the pass
NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding];
if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
} else {
[UIAlertView error:#"Password can't be sent"];
return;
}
//check whether it's a login or register
NSString* command = (sender.tag==1)?#"register":#"login";
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:command, #"command", fldUsername.text, #"username", hashedPassword, #"password", nil];
//make the call to the web API
[[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) {
//result returned
NSDictionary* res = [[json objectForKey:#"result"] objectAtIndex:0];
if ([json objectForKey:#"error"]==nil && [[res objectForKey:#"IdUser"] intValue]>0) {
[[API sharedInstance] setUser: res];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
//show message to the user
[[[UIAlertView alloc] initWithTitle:#"Logged in" message:[NSString stringWithFormat:#"Welcome %#",[res objectForKey:#"username"]] delegate:nil cancelButtonTitle:#"Close" otherButtonTitles: nil] show];
} else {
//error
[UIAlertView error:[json objectForKey:#"error"]];
}
}];
}
#end
You need to import UIKit.
#import <UIKit/UIKit.h>
Related
I'm working on an application that has a functioning keyboard with editing capabilities. In the mainViewController.m file, I am able to properly hide the keyboard with the following line of code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
After completing the main functionality of the application, I've created a simple login screen. However, the same code as above is not working in the loginScreen.m file.
#implementation LoginScreen
-(void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(IBAction)btnLoginRegisterTapped:(UIButton*)sender
{
//form fields validation
if (fldUsername.text.length < 4 || fldPassword.text.length < 4) {
[UIAlertView error:#"Enter username and password over 4 chars each."];
return;
}
//salt the password
NSString* saltedPassword = [NSString stringWithFormat:#"%#%#", fldPassword.text, kSalt];
// Check for name/pw length
//prepare the hashed storage
NSString* hashedPassword = nil;
unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
//hash the pass
NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding];
if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
} else {
[UIAlertView error:#"Password can't be sent"];
return;
}
//check whether it's a login or register
NSString* command = (sender.tag==1)?#"register":#"login";
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:
command, #"command",
fldUsername.text, #"username",
hashedPassword, #"password",
nil];
//make the call to the web API
[[API sharedInstance] commandWithParams:params
onCompletion:^(NSDictionary *json) {
//result returned
NSDictionary* res = [[json objectForKey:#"result"] objectAtIndex:0];
if ([json objectForKey:#"error"]==nil && [[res objectForKey:#"IdUser"] intValue]>0) {
[[API sharedInstance] setUser: res];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
//show message to the user
[[[UIAlertView alloc] initWithTitle:#"Logged in"
message:[NSString stringWithFormat:#"Welcome %#",[res objectForKey:#"username"] ]
delegate:nil
cancelButtonTitle:#"Close"
otherButtonTitles: nil] show];
} else {
//error
[UIAlertView error:[json objectForKey:#"error"]];
}
}];
}
#end
If I figure out the fix, I'll add it here but I'm not sure what is causing this problem, any help would be appreciated.
You can use tap gesture to hide keyboard
-(void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer =[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[self.view addGestureRecognizer:tapGestureRecognizer];
}
-(void)tapReceived:(UITapGestureRecognizer *)tapGestureRecognizer {
[self.view endEditing:YES];
[yourtextfield resignFirstResponder];
}
Step by step how would I segue a user after authentication seen below?
//curent code in viewcontroller2.h
-(IBAction)btnLoginRegisterTapped:(UIButton*)sender {
//form fields validation
if (fldUsername.text.length < 4 || fldPassword.text.length < 4) {
[UIAlertView error:#"Enter username and password over 4 chars each."];
return;
}
//salt the password
NSString* saltedPassword = [NSString stringWithFormat:#"%#%#", fldPassword.text, kSalt];
//prepare the hashed storage
NSString* hashedPassword = nil;
unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
//hash the pass
NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding];
if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
} else {
[UIAlertView error:#"Password can't be sent"];
return;
}
//check whether it's a login or register
NSString* command = (sender.tag==1)?#"register":#"login";
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:command, #"command", fldUsername.text, #"username", hashedPassword, #"password", nil];
//make the call to the web API
[[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) {
//result returned
NSDictionary* res = [[json objectForKey:#"result"] objectAtIndex:0];
if ([json objectForKey:#"error"]==nil && [[res objectForKey:#"IdUser"] intValue]>0) {
[[API sharedInstance] setUser: res];
//this doesn't dismiss anything; its leftover from another tutorial =)
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
//show message to the user
[[[UIAlertView alloc] initWithTitle:#"Logged in" message:[NSString stringWithFormat:#"Welcome %#",[res objectForKey:#"username"]] delegate:nil cancelButtonTitle:#"Close" otherButtonTitles: nil] show];
} else {
//error
[UIAlertView error:[json objectForKey:#"error"]];
}
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Would connecting a sufficient segue on the storyboard and putting this above didrecievememory warning suffice or no?
if (![[API sharedInstance] isAuthorized]) {
[self performSegueWithIdentifier:#"ShowLogin" sender:nil];
}
How does one go about creating segues from the storyboard ? I've seen these 3 links but still need a firm answer in creating a segue after a login. Custom segue after successful login http://www.raywenderlich.com/50308/storyboards-tutorial-in-ios-7-part-1 https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomSegues/CreatingCustomSegues.html
performSegueWithIdentifier is correct. You need to make sure you execute this on the main thread -
NSString* command = (sender.tag==1)?#"register":#"login";
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:command, #"command", fldUsername.text, #"username", hashedPassword, #"password", nil];
//make the call to the web API
[[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) {
//result returned
NSDictionary* res = [[json objectForKey:#"result"] objectAtIndex:0];
if ([json objectForKey:#"error"]==nil && [[res objectForKey:#"IdUser"] intValue]>0) {
[[API sharedInstance] setUser: res];
dispatch_async(dispatch_get_main_queue(),^{
[self performSegueWithIdentifier:#"someIdentifier" sender:self];
});
} else {
//error
[UIAlertView error:[json objectForKey:#"error"]];
}
}];
You will need to make sure "someIdentifier" is the identifier of the segue in your login scene to your next scene. To create the segue, ctrl drag from your View Controller icon in your login scene to the destination scene and give the segue an identifier.
You only need to create a custom segue if you want to alter the visual appearance of the segue.
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 am trying to make a jabber chat application using the xmppframework.
I have implemented the xmppStream methods in the applicationAppDelegate, but none of these method has been invoked.
Here is the code of the applicationAppDelegate:
- (void)setupStream {
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//[self connect];
}
- (void)goOnline {
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:#"unavailable"];
[[self xmppStream] sendElement:presence];
}
- (BOOL)connect {
[self setupStream];
NSString *emailUserDefault = [[NSUserDefaults standardUserDefaults] stringForKey:#"email"];
NSString *jabberID = [emailUserDefault stringByAppendingString:#"#server.local"];
NSLog(#"%#",jabberID);
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"password"];
NSLog(#"%#",myPassword);
if (![xmppStream isDisconnected]) {
NSLog(#"You are connected");
return YES;
}
if (jabberID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
//xmppStream.myJID = [XMPPJID jidWithString:jabberID];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:20 error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
- (void)disconnect {
[self goOffline];
[xmppStream disconnect];
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
isOpen = YES;
NSError *error = nil;
[[self xmppStream] authenticateWithPassword:password error:&error];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[__chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"server.local"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[__chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"server.local"]];
}
}
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSString *msg = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:msg forKey:#"msg"];
[m setObject:from forKey:#"sender"];
[__messageDelegate newMessageReceived:m];
}
Here my code for the chatViewController classe:
- (myApplicationAppDelegate *)appDelegate {
return (myApplicationAppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (XMPPStream *)xmppStream {
return [[self appDelegate] xmppStream];
}
- (void)viewDidLoad
{
[super viewDidLoad];
onlineBuddies = [[NSMutableArray alloc ] init];
myApplicationAppDelegate *del = [self appDelegate];
[self xmppStream];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:#"email"];
del._chatDelegate = self;
if (login) {
if ([[self appDelegate] connect]) {
NSLog(#"show buddy list");
}
} else {
NSLog(#"Login Error");
}
}
I cannot figure out why the xmpp delegate methods are not being invoked. If someone can give me a hand, please don't hesitate.
Thanks in advance.
I think you misunderstood the purpose of AppDelegate. First of all for every iOS app that you are creating in Xcode there is a class created that contains the name AppDelegate but this class should only be used to get information of your application state, such as if the app goes to background, if it's launched with success or if it's coming up from background. Also the app delegate is used to specify the root (or entry point) view controller of your application.
So I think you should first check the basic rules (or a basic tutorial) on how to create a very simple application (a "Hello World Application"), after that you can go forward and create a basic structure of your application and decide what view controller or what model classes will handle your connection handling and response/request parsing.
I strongly suggest that you have a look over view controllers and I'm pretty sure that after you do the above suggested "tasks" you will answer yourself the posted question.
P.S Last point, have a look on "iOS naming & other conventions"enter link description herelife cycle methods
I am using GMTOAuth2 in an application with one viewController and it works fine, Then I add same code to another application that contains more viewControllers, It loads the webView with textfields for username and password but if I click on anything in this view it crashes with Thread 1: EXC_BAD_ACCESS (code=2, address=0xbf7ffffc) with void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode in the console. My code for authorization part looks like this:
- (void)awakeFromNib {
[super awakeFromNib];
GTMOAuth2Authentication *auth = nil;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kMyClientID
clientSecret:kMyClientSecret];
if (auth)
{
[auth authorizeRequest:nil
delegate:self
didFinishSelector:#selector(authentication:request:finishedWithError:)];
}
}
- (void)signInToGoogle {
[self signOut];
NSString *keychainItemName = kKeychainItemName;
NSString *scope = #"https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
NSString *clientID = kMyClientID;
NSString *clientSecret = kMyClientSecret;
if ([clientID length] == 0 || [clientSecret length] == 0) {
NSString *msg = #"The sample code requires a valid client ID and client secret to sign in.";
[self displayAlertWithMessage:msg];
return;
}
SEL finishedSel = #selector(viewController:finishedWithAuth:error:);
GTMOAuth2ViewControllerTouch *viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:scope
clientID:clientID
clientSecret:clientSecret
keychainItemName:keychainItemName
finishedSelector:finishedSel];
delegate:self
[self presentViewController:viewController animated:YES completion:^{}];
[[self navigationController] pushViewController:viewController animated:YES];
}
- (void)authentication:(GTMOAuth2Authentication *)auth
request:(NSMutableURLRequest *)request
finishedWithError:(NSError *)error {
if (error != nil) {
NSLog(#"error!");
} else {
[self isAuthorizedWithAuthentication:auth];
self.auth = auth;
}
}
And copied the same class from first application to second one, and made exactly same nib file.