Question

I have subclassed UIAlertView and inside which I am showing a textField which takes the input. When user clicks on textField the keyboard shows up and UIAlertView moves up to adjust for keyboard. But when I do [textField becomeFirstResponder] in didPresentAlertView delegate method of UIAlertView, the alertView doesn't moves up to adjust for keyboard. Instead the UIAlertView gets hidden behind the keyboard.

PS - I know that Apple says that UIAlertView should not be subclassed and to be used as it is, but I am subclassing UIAlertView because I want to redesign the Apple's default UI elements in it.

Was it helpful?

Solution

You should really not do something against Apple's recommendation.

Reasons

  1. You can face unexpected issues like the one you are facing.
  2. Your code can break for future iOS releases as you are violating recommendations.
  3. Redesigning Apple's standard controls is in violation of HIG guidelines. As a result, there is a chance that your app can get rejected. Create your own instead, by using UIView subclass.

As an alternative, Apple has made provision in the UIAlertView for this requirement. You don't need to add a textfield to the alert view, instead, use the UIAlertView property alertViewStyle. It accepts values defined in the enum UIAlertViewStyle

typedef NS_ENUM(NSInteger, UIAlertViewStyle) {
    UIAlertViewStyleDefault = 0,
    UIAlertViewStyleSecureTextInput, // Secure text input
    UIAlertViewStylePlainTextInput,  // Plain text input
    UIAlertViewStyleLoginAndPasswordInput // Two text fields, one for username and other for password
};

Example, lets assume a use case that you want to accept password from the user. The code to achieve this is as below.

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Please enter password"
                                                  message:nil
                                                 delegate:self
                                        cancelButtonTitle:@"Cancel"
                                        otherButtonTitles:@"Continue", nil];
[alert setAlertViewStyle:UIAlertViewStyleSecureTextInput];
[alert show];

To validate the input, lets say password entered must be minimum 6 characters, implement this delegate method,

- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
    NSString *inputText = [[alertView textFieldAtIndex:0] text];
    if( [inputText length] >= 6 )
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

To get the user input

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
    if([title isEqualToString:@"Login"])
    {
        UITextField *password = [alertView textFieldAtIndex:0];
        NSLog(@"Password: %@", password.text);
    }
}

To re-iterate, UIAlertView has a private view hierarchy and it is recommended to use it as-is without modification. If you use it against recommendation you will get unexpected results.

From Apple docs

The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

This is standard technique used even in iOS default apps (Ex: Entering Wi-Fi password, etc.), hence using this will ensure you don't face issues like the one you mention.

Hope that helps!

OTHER TIPS

I do like this to upthe screen to show the textfiled. :-) Hope this help you.

- (void) textFieldDidBeginEditing:(UITextField *)textField {

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = CGRectMake(( self.view.frame.origin.x), (self.view.frame.origin.y-50 ), self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}


 - (void) textFieldDidEndEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+50 , self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top