Skip to content
Browse files

Fix Login Button for iOS 5 Devices

We have a tap gesture recognizer to identify when the UITableView was touched, so
we can dismiss the keyboard if a user touches outside of the text field. For some
reason iOS 5 would cancel the event of a button being pushed
(iOS 4 and 6 had no issues with this). To make this very hard to break for all
3 versions, I use reflection to check to see if the view that belongs to the
tap gesture event is of class UIButton. If we are touching a button that belongs
to the UITableView, then return false, which will prevent calling the selector
method tableViewTapped:tapGesture.
  • Loading branch information...
1 parent 8587624 commit 14a4ec51e7fe6e846921bac2ea5296e8a54e4437 @BaseInfinity BaseInfinity committed Mar 12, 2013
Showing with 70 additions and 64 deletions.
  1. +1 −1 Classes/LoginViewController.h
  2. +69 −63 Classes/LoginViewController.m
View
2 Classes/LoginViewController.h
@@ -9,7 +9,7 @@
@class WBProgressHUD;
#import "LoginViewControllerDelegate.h"
-@interface LoginViewController : UITableViewController <UITextFieldDelegate>
+@interface LoginViewController : UITableViewController <UITextFieldDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, assign) id<LoginViewControllerDelegate> delegate;
@property (nonatomic, copy) NSString *message;
View
132 Classes/LoginViewController.m
@@ -53,10 +53,10 @@ - (void)textFieldDidEndEditing:(UITextField *)textField {
}
- (void)showMessage {
- if ([emailField isFirstResponder] || [passwordField isFirstResponder] ||
+ if ([emailField isFirstResponder] || [passwordField isFirstResponder] ||
[passwordVerifyField isFirstResponder] || [fullNameField isFirstResponder])
return;
-
+
[UIView beginAnimations:@"repositionForm" context:nil];
[UIView setAnimationDuration:0.3];
self.tableView.contentInset = UIEdgeInsetsMake(5, 0, 0, 0);
@@ -83,15 +83,15 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField {
else {
[self sendLogin];
}
-
+
return YES;
}
- (void)showLoading {
if (!loading) {
self.loading = [[[WBProgressHUD alloc] init] autorelease];
}
-
+
CGFloat width = 160;
CGFloat height = 120;
self.loading.frame = CGRectMake((self.view.frame.size.width - width) / 2.0,
@@ -102,40 +102,40 @@ - (void)showLoading {
// Hide the keyboard and prevent further editing.
self.view.userInteractionEnabled = NO;
[self.view endEditing:YES];
-
+
[loading showInView:self.tableView];
}
- (void)hideLoading {
[loading removeFromSuperview];
-
+
// Allow editing again.
self.view.userInteractionEnabled = YES;
}
- (void)dealloc {
[message release];
[loading release];
-
+
[emailField release];
[passwordField release];
[passwordVerifyField release];
[fullNameField release];
-
+
[loginButton release];
[registerButton release];
[cancelButton release];
[googleButton release];
[yahooButton release];
-
+
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
-
+
// Release any cached data, images, etc that aren't in use.
}
@@ -154,7 +154,7 @@ - (UIView *)createMessage {
l.shadowOffset = CGSizeMake(0.0, 1.0);
l.numberOfLines = 0;
l.text = message;
-
+
[container addSubview:l];
[l sizeToFit];
@@ -164,20 +164,20 @@ - (UIView *)createMessage {
container.frame = CGRectMake(0, 0, 320, frame.size.height + 10);
l.frame = frame;
[l release];
-
+
return [container autorelease];
}
- (UIView *)createActionButtons {
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
-
+
// Login
UIButton *lb = [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 300, 45)];
lb.autoresizingMask = UIViewAutoresizingFlexibleWidth;
lb.titleLabel.font = [UIFont boldSystemFontOfSize:18.0];
lb.titleLabel.shadowColor = [UIColor blackColor];
lb.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0);
-
+
[lb setTitle:@"Login" forState:UIControlStateNormal];
[lb setBackgroundImage:[[UIImage imageNamed:@"login.png"] stretchableImageWithLeftCapWidth:150 topCapHeight:22] forState:UIControlStateNormal];
[lb setContentMode:UIViewContentModeScaleToFill];
@@ -187,25 +187,25 @@ - (UIView *)createActionButtons {
if ([[[[UIApplication sharedApplication].delegate window] rootViewController] isKindOfClass:[LoginBackgroundViewController class]]) {
lb.frame = CGRectMake(30, 0, 260, 45);
}
-
+
// Register
UIButton *rb = [[UIButton alloc] initWithFrame:CGRectMake(10, 55, 300, 45)];
rb.autoresizingMask = UIViewAutoresizingFlexibleWidth;
rb.titleLabel.font = [UIFont boldSystemFontOfSize:18.0];
rb.titleLabel.shadowColor = [UIColor blackColor];
rb.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0);
-
+
[rb setTitle:@"Create an Account" forState:UIControlStateNormal];
[rb setBackgroundImage:[[UIImage imageNamed:@"register.png"] stretchableImageWithLeftCapWidth:150 topCapHeight:22] forState:UIControlStateNormal];
[lb setContentMode:UIViewContentModeScaleToFill];
[rb addTarget:self action:@selector(toggleRegister) forControlEvents:UIControlEventTouchUpInside];
-
+
// Cancel
UIButton *cb = [[UIButton alloc] initWithFrame:CGRectMake(10, 55, 300, 35)];
cb.autoresizingMask = UIViewAutoresizingFlexibleWidth;
cb.titleLabel.font = [UIFont systemFontOfSize:16.0];
cb.titleLabel.shadowOffset = CGSizeMake(0.0, 1.0);
-
+
[cb setTitle:@"Cancel" forState:UIControlStateNormal];
[cb setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[cb setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateNormal];
@@ -234,7 +234,7 @@ - (UIView *)createActionButtons {
[cb release];
[gb release];
[yb release];
-
+
[container addSubview:loginButton];
if (![Config currentConfig].sso && ![Config currentConfig].private) {
@@ -269,21 +269,21 @@ - (void)tapYahoo {
- (void)toggleRegister {
showRegister = !showRegister;
-
+
NSArray *indexPaths = [NSArray arrayWithObjects:
- [NSIndexPath indexPathForRow:2 inSection:0],
+ [NSIndexPath indexPathForRow:2 inSection:0],
[NSIndexPath indexPathForRow:3 inSection:0], nil];
if (showRegister) {
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[UIView beginAnimations:@"showRegister" context:nil];
[UIView setAnimationDuration:0.3];
-
+
// Hide login
loginButton.alpha = 0.0;
googleButton.alpha = 0.0;
yahooButton.alpha = 0.0;
-
+
// Move Register up, change text, and change target
CGRect frame = registerButton.frame;
frame.origin.y = 0;
@@ -294,14 +294,14 @@ - (void)toggleRegister {
// Show Cancel
cancelButton.alpha = 1.0;
-
+
[UIView commitAnimations];
}
else {
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[UIView beginAnimations:@"showRegister" context:nil];
[UIView setAnimationDuration:0.3];
-
+
// Show Login
loginButton.alpha = 1.0;
googleButton.alpha = 1.0;
@@ -317,34 +317,40 @@ - (void)toggleRegister {
// Hide Cancel
cancelButton.alpha = 0.0;
-
+
[UIView commitAnimations];
}
-
+
// Change the password action item from "Done" to "Next" or back again.
passwordField.returnKeyType = showRegister ? UIReturnKeyNext : UIReturnKeyDone;
}
- (void)viewDidLoad {
[super viewDidLoad];
- // Adds ability to check when a user touches UITableView only
- UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
- initWithTarget:self
- action:@selector(tableViewTapped:)];
- [[self tableView] addGestureRecognizer:tapGesture];
-
- [tapGesture release];
-
self.title = @"Login";
self.tableView.backgroundView = nil;
self.view.backgroundColor = [UIColor colorWithRed:0.86 green:0.86 blue:0.86 alpha:1.0];
-
+
self.tableView.tableHeaderView = [self createMessage];
self.tableView.tableFooterView = [self createActionButtons];
self.tableView.contentInset = UIEdgeInsetsMake(5, 0, 0, 0);
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+
+ // Adds ability to check when a user touches UITableView only
+ UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
+ initWithTarget:self
+ action:@selector(tableViewTapped:)];
+
+ tapGesture.delegate = self;
+ [[self tableView] addGestureRecognizer:tapGesture];
+ [tapGesture release];
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
+ // If the user is trying to select a button on the tableview, don't return the touch event
+ return ![touch.view isKindOfClass:[UIButton class]];
}
- (void)tableViewTapped:(UITapGestureRecognizer *)tapGesture {
@@ -360,7 +366,7 @@ - (void)viewDidUnload {
self.passwordField = nil;
self.passwordVerifyField = nil;
self.fullNameField = nil;
-
+
self.loginButton = nil;
self.registerButton = nil;
self.cancelButton = nil;
@@ -393,19 +399,19 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
}
- (UITextField *)inputFieldForRow:(NSInteger)row {
-
+
UITextField *inputField = [[UITextField alloc] init];
inputField.font = [UIFont systemFontOfSize:16.0];
inputField.adjustsFontSizeToFitWidth = YES;
inputField.textColor = [UIColor darkGrayColor];
CGRect rect = CGRectMake(120, 12, 175, 30);
-
+
if (row == 0) {
if (emailField) {
[inputField release];
return emailField;
}
-
+
self.emailField = inputField;
rect.origin.y += 1;
inputField.frame = rect;
@@ -420,61 +426,61 @@ - (UITextField *)inputFieldForRow:(NSInteger)row {
passwordField.returnKeyType = showRegister ? UIReturnKeyNext : UIReturnKeyDone;
return passwordField;
}
-
+
self.passwordField = inputField;
inputField.frame = rect;
inputField.placeholder = @"Required";
inputField.keyboardType = UIKeyboardTypeDefault;
inputField.returnKeyType = showRegister ? UIReturnKeyNext : UIReturnKeyDone;
inputField.secureTextEntry = YES;
- }
+ }
else if (row == 2) {
if (passwordVerifyField) {
[inputField release];
return passwordVerifyField;
}
-
+
self.passwordVerifyField = inputField;
inputField.frame = rect;
inputField.placeholder = @"(again)";
inputField.keyboardType = UIKeyboardTypeDefault;
inputField.returnKeyType = UIReturnKeyNext;
inputField.secureTextEntry = YES;
- }
+ }
else if (row == 3) {
if (fullNameField) {
[inputField release];
return fullNameField;
}
-
+
self.fullNameField = inputField;
inputField.frame = rect;
inputField.placeholder = @"John Doe";
inputField.keyboardType = UIKeyboardTypeDefault;
inputField.returnKeyType = UIReturnKeyDone;
- }
+ }
inputField.backgroundColor = [UIColor clearColor];
inputField.autocorrectionType = UITextAutocorrectionTypeNo;
inputField.autocapitalizationType = UITextAutocapitalizationTypeWords;
inputField.textAlignment = UITextAlignmentLeft;
inputField.delegate = self;
inputField.tag = 0;
-
+
inputField.clearButtonMode = UITextFieldViewModeNever;
[inputField setEnabled:YES];
-
+
return [inputField autorelease];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
-
+
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
-
+
// Set the label
if (indexPath.row == 0)
cell.textLabel.text = @"Email";
@@ -484,15 +490,15 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
cell.textLabel.text = @"Password";
else if (indexPath.row == 3)
cell.textLabel.text = @"Your Name";
-
+
// Add the text field
for (UIView *v in cell.subviews) {
if ([v isKindOfClass:[UITextField class]])
[v removeFromSuperview];
}
-
+
[cell.contentView addSubview:[self inputFieldForRow:indexPath.row]];
-
+
return cell;
}
@@ -507,17 +513,17 @@ - (void)sendLogin {
if (!emailField.text || !passwordField.text)
return;
-
+
[self showLoading];
[[iFixitAPI sharedInstance] loginWithLogin:emailField.text
- andPassword:passwordField.text
- forObject:self
+ andPassword:passwordField.text
+ forObject:self
withSelector:@selector(loginResults:)];
}
- (void)sendRegister {
if (!emailField.text || !passwordField.text || !passwordVerifyField.text || !fullNameField.text) {
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"All fields are required"
delegate:nil
cancelButtonTitle:nil
@@ -526,7 +532,7 @@ - (void)sendRegister {
[alert release];
}
else if (![passwordVerifyField.text isEqual:passwordField.text]) {
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Passwords don't match"
delegate:nil
cancelButtonTitle:nil
@@ -537,16 +543,16 @@ - (void)sendRegister {
else {
[self showLoading];
[[iFixitAPI sharedInstance] registerWithLogin:emailField.text
- andPassword:passwordField.text
- andName:fullNameField.text
+ andPassword:passwordField.text
+ andName:fullNameField.text
forObject:self
withSelector:@selector(loginResults:)];
}
}
-- (void)loginResults:(NSDictionary *)results {
+- (void)loginResults:(NSDictionary *)results {
if ([results objectForKey:@"error"]) {
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:[results objectForKey:@"msg"]
delegate:nil
cancelButtonTitle:nil
@@ -563,7 +569,7 @@ - (void)loginResults:(NSDictionary *)results {
// The delegate is responsible for removing the login view.
[delegate refresh];
}
-
+
[self hideLoading];
}

0 comments on commit 14a4ec5

Please sign in to comment.
Something went wrong with that request. Please try again.