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];
}
Related
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>
I am having a screen for adding a reminder. The screen is having 2 textfields and 1 textview. These all are under scrollView which is a subclass of TPAvoidingScrollView class. This class itself manages the position of scrollView and hence the components inside as the keyboard appears and disappears.
The screen is as follows.
After I have gone through all the fields and selected certain values. By clicking on Add reminder the event is added into the main calendar and the screen pops out to the previous screen. And then problem starts to occur. As soon as I again comes to this screen and tapping on the Textview Notes the app crashes with these errors.
Here Reminder view controller is the name of the class
The code for the whole class is:
#import "ReminderViewController.h"
#import <EventKit/EventKit.h>
#import "ActionSheetPicker.h"
#import "NSDate-Utilities.h"
#interface ReminderViewController ()
#end
#implementation ReminderViewController
#synthesize scrollView;
#synthesize txt_notes;
#synthesize txt_remindOn;
#synthesize txt_repeatAlarm;
#synthesize btn_appointment;
#synthesize btn_pickup;
#synthesize btn_reminder;
#synthesize txt_currentFocussedTextField;
#synthesize selectedDate;
#synthesize arr_repeatAlarm;
#synthesize selectedIndex;
#synthesize isSelected;
#synthesize str_eventTitle;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = CGSizeMake(320, 520);
self.selectedDate = [NSDate date];
self.arr_repeatAlarm = [NSArray arrayWithObjects:#"None",#"Every Day", #"Every Week",
#"Every Month", #"Every year", nil];
btn_reminder.backgroundColor =[UIColor colorWithRed:0.0/255 green:89.0/255 blue:178.0/255
alpha:1.0f];
[[AppDelegate sharedInstance] setUpHighlightedStateOfButton:btn_reminder];
// Do any additional setup after loading the view.
}
#pragma mark - Check button click methods
-(IBAction)btn_appointment_click:(id)sender{
if(btn_appointment.selected){
[btn_appointment setSelected:NO];
[btn_pickup setSelected:YES];
isSelected = NO;
}
else{
[btn_appointment setSelected:YES];
[btn_pickup setSelected:NO];
isSelected = YES;
}
}
-(IBAction)btn_pickup_click:(id)sender{
if(btn_pickup.selected){
[btn_pickup setSelected:NO];
[btn_appointment setSelected:YES];
isSelected = NO;
}
else{
[btn_pickup setSelected:YES];
[btn_appointment setSelected:NO];
isSelected = YES;
}
}
#pragma mark - calendar Event methods
- (IBAction)btn_reminder_click:(id)sender{
[self addEventTocalendar:sender];
}
- (void)addEventTocalendar:(id)sender{
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError
*error) {
if (!granted) { return; }
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = #"Pickup Reminder";
event.startDate = self.selectedDate;
event.endDate = [event.startDate dateByAddingTimeInterval:60*60];//set 1 hour meeting
event.notes = txt_notes.text;
event.recurrenceRules = EKRecurrenceFrequencyDaily;
[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -5.0f]];
if (selectedIndex == 1) {
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyDaily interval:1 end:Nil]];
}
else if (selectedIndex == 2){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyWeekly interval:1 end:Nil]];
}
else if (selectedIndex == 3){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly interval:1 end:Nil]];
}
else if (selectedIndex == 4){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyYearly interval:1 end:Nil]];
}
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *err = nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
NSString *savedEventId = event.eventIdentifier; //this is so you can access this
event later
BOOL isSuceess=[store saveEvent:event span:EKSpanThisEvent error:&err];
// This needs to be done as the UIKIT was getting called from the seconadary thread
and therefore to show the alert view in the main thread and to prevent the hanging of
the app I have to call the Aletview method in the main thread.
// i.e dispatch the event in the main thread
if(isSuceess){
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"Event"
message:#"Event added in calendar" delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[alertview show];
});
}
else {
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"Event" message:[err
description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[alertview show];
});
}
}];
}
- (void)back{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - UIAlertViewDelegate methods
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Implementation methods
- (void)serviceWasSelected:(NSNumber *)selectedIndex element:(id)element {
self.selectedIndex = [selectedIndex intValue];
//may have originated from textField or barButtonItem, use an IBOutlet instead of element
self.txt_repeatAlarm.text = [self.arr_repeatAlarm objectAtIndex:self.selectedIndex];
}
- (void)dateWasSelected:(NSDate *)selectedDate element:(id)element{ //indexpath:
(NSIndexPath *)indexpath{
UITextField * textfield = (UITextField *)element;
if (textfield == self.txt_remindOn) {
self.selectedDate = selectedDate;
self.txt_remindOn.text = [self.selectedDate getDateStringInFormat:#"dd MMM yyyy
hh:mm aa"];
}
}
#pragma mark - TextField Delegate Methods
- (void)textFieldDidBeginEditing:(UITextField *)textField{
self.txt_currentFocussedTextField = textField;
[[AppDelegate sharedInstance] addToolbarForKeyboard:textField];
if (textField == self.txt_remindOn) {
[textField resignFirstResponder];
_actionSheetPicker = [[ActionSheetDatePicker alloc] initWithTitle:#""
datePickerMode:UIDatePickerModeDateAndTime selectedDate:self.selectedDate
minimumDate:[NSDate
date] maximumDate:Nil target:self action:#selector(dateWasSelected:element:)
origin:textField];
self.actionSheetPicker.hideCancel = NO;
[self.actionSheetPicker showActionSheetPicker];
}
if (textField == self.txt_repeatAlarm) {
[textField resignFirstResponder];
[ActionSheetStringPicker showPickerWithTitle:#"" rows:self.arr_repeatAlarm
initialSelection:self.selectedIndex target:self
successAction:#selector(serviceWasSelected:element:)
cancelAction:#selector(actionPickerCancelled:) origin:textField];
}
}
// making the keyboard disappear on pressing the Done button on the keyboard.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I am trying to implement a sign up process with a parse backend. I have a validation method called processFieldEntries and once the done button gets enabled, I try to trigger the segue that I setup modally from my view controller(not from the done button) from view did appear method but neither the validation method gets called nor the segue gets triggered. I setup some debug and logging breakpoints for debugging but, I couldn't go any further apart from the fact that it does not see the view did load. I also tried setting up the segue from the done button. When I did that, the segue gets triggered, not from the code but from storyboard my storyboard here. If someone can help me to figure out how to call processfieldentriees along with the segue, I would really appreciate. Thank you.
NewUserSignUpViewController.h
#import <UIKit/UIKit.h>
#import "ProfileViewController.h"
#interface NewUserSignUpViewController : UIViewController<UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UIBarButtonItem *barButtonItem;
#property (strong, nonatomic) IBOutlet UITextField *usernameField;
#property (strong, nonatomic) IBOutlet UITextField *passwordField;
#property (strong, nonatomic) IBOutlet UITextField *repeatPasswordField;
- (IBAction)doneEvent:(id)sender;
- (IBAction)cancelEvent:(id)sender;
#end
NewUserSignUpViewController.m
#import "NewUserSignUpViewController.h"
#import "ProfileViewController.h"
#import <Parse/Parse.h>
#import "ActivityView.h"
#interface NewUserSignUpViewController ()
-(void)processFieldEntries;
- (void)textInputChanged:(NSNotification *)note;
- (BOOL)shouldEnableDoneButton;
#end
#implementation NewUserSignUpViewController
#synthesize barButtonItem = _doneButtonInTheBar;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_usernameField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_passwordField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_repeatPasswordField];
}
-(void)viewDidAppear:(BOOL)animated
{
[_usernameField becomeFirstResponder];
[super viewDidAppear:animated];
//perform the segue
if (_doneButtonInTheBar.enabled == YES) {
[self performSegueWithIdentifier:#"segueToProfileView" sender:self];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
}
#pragma mark - UITextFieldDelegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{ textField.delegate = self;
if (textField == _usernameField) {[_usernameField becomeFirstResponder];}
if (textField == _passwordField){[_passwordField becomeFirstResponder];}
if (textField == _repeatPasswordField)
{
[_repeatPasswordField becomeFirstResponder];
[self processFieldEntries];
}
return YES;
}
-(BOOL)shouldEnableDoneButton
{
BOOL enableDoneButton = NO;
if (_usernameField.text != nil && _usernameField.text.length != 0 &&_passwordField.text != nil &&
_passwordField.text.length !=0 && _repeatPasswordField.text != nil &&
_repeatPasswordField.text.length != 0) {
enableDoneButton = YES;
[self processFieldEntries];
}
return enableDoneButton;
}
-(void)textInputChanged:(NSNotification *)note
{
_doneButtonInTheBar.enabled = [ self shouldEnableDoneButton];
}
- (IBAction)doneEvent:(id)sender {
[_usernameField resignFirstResponder];
[_passwordField resignFirstResponder];
[_repeatPasswordField resignFirstResponder];
NSLog(#"processfieldentries");
[self processFieldEntries];
}
- (IBAction)cancelEvent:(id)sender {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)processFieldEntries
{
// Check that we have a non-zero username and passwords.
// Compare password and passwordAgain for equality
// Throw up a dialog that tells them what they did wrong if they did it wrong.
NSString *username = _usernameField.text;
NSString *password = _passwordField.text;
NSString *passwordAgain = _repeatPasswordField.text;
NSString *errorText = #"Please ";
NSString *usernameBlankText = #"enter a username";
NSString *passwordBlankText = #"enter a password";
NSString *joinText = #", and ";
NSString *passwordMismatchText = #"enter the same password twice";
BOOL textError = NO;
// Messaging nil will return 0, so these checks implicitly check for nil text.
if (username.length == 0 || password.length == 0 || passwordAgain.length == 0) {
textError = YES;
//setting the keyboard for th first missing output
if (passwordAgain.length == 0) {
[_repeatPasswordField becomeFirstResponder];
}
if (password.length == 0) {
[_passwordField becomeFirstResponder];
}
if (username.length == 0) {
[_usernameField becomeFirstResponder];
}
if (username.length == 0) {
errorText = [errorText stringByAppendingString:usernameBlankText];
}
if (password.length == 0 || passwordAgain.length == 0) {
if (username.length == 0) { // We need some joining text in the error:
errorText = [errorText stringByAppendingString:joinText];
}
errorText = [errorText stringByAppendingString:passwordBlankText];
}
}else if ([password compare:passwordAgain] != NSOrderedSame)
{errorText = [errorText stringByAppendingString:passwordMismatchText];
[_passwordField becomeFirstResponder];}
if (textError) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:errorText message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
return;
// Everything looks good; try to log in.
// Disable the done button for now.
_doneButtonInTheBar.enabled = NO;
ActivityView *activityView = [[ActivityView alloc]initWithFrame:CGRectMake(0.f, 0.f, self.view.frame.size.width, self.view.frame.size.height)];
UILabel *label = activityView.label;
label.text = #"signing up";
label.font = [UIFont boldSystemFontOfSize:20.0f];
[activityView.activityIndicator startAnimating];
[activityView layoutSubviews];
[self.view addSubview:activityView];
// Call into an object somewhere that has code for setting up a user.
// The app delegate cares about this, but so do a lot of other objects.
// For now, do this inline.
NSLog(#"does it reach here");
PFUser *user = [PFUser user];
user.username = username;
user.password = password;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
_doneButtonInTheBar.enabled = [self shouldEnableDoneButton];
[activityView.activityIndicator stopAnimating];
[activityView removeFromSuperview];
// Bring the keyboard back up, because they'll probably need to change something.
[_usernameField becomeFirstResponder];
return;
}
// Success!
[activityView.activityIndicator stopAnimating];
[activityView removeFromSuperview];
}];
}
}
#end
You could try not to use performSegueWithIdentifier inside viewDidAppear (performSegue actually take you to the other ViewController). Instead you could call it from an IBAction method connected to the done button, after calling in the same method processFieldEntries. I hope this can help you :)
I am trying to setup a signup view with using parse.com as backend but for some reason whenever i start typing in the reenter password field, as soon as i type something, it starts going through this
else if ([password compare:passwordAgain] != NSOrderedSame) {
// We have non-zero strings.
// Check for equal password strings.
textError = YES;
errorText = [errorText stringByAppendingString:passwordMismatchText];
[_reEnterPasswordField becomeFirstResponder];
NSLog(#"stops here");
}
method and sends me the error message passwordMismatchText. It goes through this message everytime i change a word whether i added or deleted it. When I use the same methods with xib the files i had no problem. But after I try to do the same thing with storyboards I am having this issue. I tried creating a user default for _doneButton.enabled == YES and put an another if around the errorText =[...] message, but did not solve the problem. I appreciate for the help.
SignUpViewController.h
#import <UIKit/UIKit.h>
#interface SignUpViewController : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *doneButton;
#property (weak, nonatomic) IBOutlet UITextField *userNameField;
#property (weak, nonatomic) IBOutlet UITextField *passwordField;
#property (weak, nonatomic) IBOutlet UITextField *reEnterPasswordField;
- (IBAction)done:(id)sender;
- (IBAction)cancel:(id)sender;
#end
SignUpViewController.m
#import "SignUpViewController.h"
#import <Parse/Parse.h>
#import "ActivityView.h"
#import "ProfileViewController.h"
#interface SignUpViewController ()
- (void)textInputChanged:(NSNotification *)note;
-(void)processFieldEntries;
- (BOOL)shouldEnableDoneButton;
#end
#implementation SignUpViewController
#synthesize doneButton = _doneButton;
#synthesize userNameField = _userNameField;
#synthesize passwordField = _passwordField;
#synthesize reEnterPasswordField = _reEnterPasswordField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter ]addObserver:self selector:#selector(textInputChanged:) name: UITextFieldTextDidChangeNotification object:_userNameField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_passwordField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_reEnterPasswordField];
_doneButton.enabled = NO;
NSLog(#"nsnotification is working fine");
}
-(void)viewWillAppear:(BOOL)animated
{
[_userNameField becomeFirstResponder];
[super viewWillAppear:animated];
NSLog(#"indeed usernamefield became a first responder");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == _userNameField ) {
[_userNameField becomeFirstResponder];
}
if (textField == _passwordField) {
[_passwordField becomeFirstResponder];
}
if (textField == _reEnterPasswordField)
{
[_reEnterPasswordField becomeFirstResponder];
}
NSLog(#"keyboard action works fine ");
return YES;
}
-(BOOL)shouldEnableDoneButton
{
BOOL enableDoneButton = NO;
if (_userNameField.text != nil &&
_userNameField.text.length > 0 &&
_passwordField.text != nil &&
_passwordField.text.length > 0 &&
_reEnterPasswordField.text != nil &&
_reEnterPasswordField.text.length > 0)
{
[self processFieldEntries];
enableDoneButton = YES;
NSLog(#"done button enabled");
}
return enableDoneButton;
}
-(void)textInputChanged:(NSNotification *)note
{
_doneButton.enabled = [self shouldEnableDoneButton];
}
- (IBAction)done:(id)sender {
[_userNameField resignFirstResponder];
[_passwordField resignFirstResponder];
[_reEnterPasswordField resignFirstResponder];
[self processFieldEntries];
NSLog(#"do you see this");
}
- (IBAction)cancel:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
-(void)processFieldEntries
{
// Check that we have a non-zero username and passwords.
// Compare password and passwordAgain for equality
// Throw up a dialog that tells them what they did wrong if they did it wrong.
NSString *username = _userNameField.text;
NSString *password = _passwordField.text;
NSString *passwordAgain = _reEnterPasswordField.text;
NSString *errorText = #"Please ";
NSString *usernameBlankText = #"enter a username";
NSString *passwordBlankText = #"enter a password";
NSString *joinText = #", and ";
NSString *passwordMismatchText = #"enter the same password twice";
BOOL textError = NO;
NSLog(#"validation begins here");
// Messaging nil will return 0, so these checks implicitly check for nil text.
if (username.length == 0 || password.length == 0 || passwordAgain.length == 0) {
textError = YES;
// Set up the keyboard for the first field missing input:
if (passwordAgain.length == 0) {
[_reEnterPasswordField becomeFirstResponder];
}
if (password.length == 0) {
[_passwordField becomeFirstResponder];
}
if (username.length == 0) {
[_userNameField becomeFirstResponder];
}
if (username.length == 0) {
errorText = [errorText stringByAppendingString:usernameBlankText];
}
if (password.length == 0 || passwordAgain.length == 0) {
if (username.length == 0) { // We need some joining text in the error:
errorText = [errorText stringByAppendingString:joinText];
}
errorText = [errorText stringByAppendingString:passwordBlankText];
}
} else if ([password compare:passwordAgain] != NSOrderedSame) {
// We have non-zero strings.
// Check for equal password strings.
textError = YES;
errorText = [errorText stringByAppendingString:passwordMismatchText];
[_reEnterPasswordField becomeFirstResponder];
NSLog(#"stops here");
}
if (textError) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:errorText message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
return;
}
NSLog(#"validation works just fine");
// Everything looks good; try to log in.
// Disable the done button for now.
_doneButton.enabled = NO;
ActivityView *activityCircle = [[ActivityView alloc] initWithFrame:CGRectMake(0.f, 0.f, self.view.frame.size.width, self.view.frame.size.height)];
UILabel *label = activityCircle.label;
label.text = #"Signing You Up";
label.font = [UIFont boldSystemFontOfSize:20.f];
[activityCircle.activityIndicator startAnimating];
[activityCircle layoutSubviews];
[self.view addSubview:activityCircle];
NSLog(#"activity view works just fine");
//parse registeration
// Call into an object somewhere that has code for setting up a user.
// The app delegate cares about this, but so do a lot of other objects.
// For now, do this inline.
PFUser *user = [PFUser user];
user.username = username;
user.password = password;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
_doneButton.enabled = [self shouldEnableDoneButton];
[activityCircle.activityIndicator stopAnimating];
[activityCircle removeFromSuperview];
// Bring the keyboard back up, because they'll probably need to change something.
[_userNameField becomeFirstResponder];
return;
}
// Success!
[activityCircle.activityIndicator stopAnimating];
[activityCircle removeFromSuperview];
//add the next screen here
}];
NSLog(#"user signedup just fine");
//now pass the view from sign up to profile view
}
/*
//this one didnt work
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ProfileViewController *myProfileView = [segue destinationViewController];
if (_doneButton.enabled == YES) {
[myProfileView performSegueWithIdentifier:#"SignUpSegue" sender:_doneButton];
}
}
*/
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
NSLog(#"is this method visible");
if (_doneButton.enabled == YES) {
[self performSegueWithIdentifier:#"SignUpSegue" sender:_doneButton];
}
return NO;
}
#end
this is the log files that I am getting
2013-09-06 02:49:19.938 nsnotification is working fine
2013-09-06 02:49:19.942 indeed usernamefield became a first responder
2013-09-06 02:49:47.446 validation begins here
2013-09-06 02:49:47.448 stops here
2013-09-06 02:49:47.485 done button enabled
2013-09-06 02:49:49.271 validation begins here
2013-09-06 02:49:49.273 stops here
2013-09-06 02:49:49.296 done button enabled
2013-09-06 02:49:51.257 validation begins here
2013-09-06 02:49:51.259 validation works just fine
2013-09-06 02:49:51.265 activity view works just fine
2013-09-06 02:49:51.270 user signedup just fine
2013-09-06 02:49:51.271 done button enabled
You are triggering the code to run by your observation of UITextFieldTextDidChangeNotification. As this moves through your methods you eventually call processFieldEntries. Probably you shouldn't be calling processFieldEntries from shouldEnableDoneButton.
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