Search code examples
objective-ccocoa-touchios6uialertview

Is it possible to make an UIAlertView with 3 textfields?


I need to input first, middle and last names when user will add a contact to his addressbook.

P.S.: Finally I found control, which allows that: https://github.com/eaigner/CODialog


Solution

  • Can you suggest something I can use instead?

    I'd present a modal view via presentViewController:animated:completion: (ios 5+) or presentModalViewController:animated: ios <5 (deprecated)

    If you want to stick with an alertview, you can find replacements on cocoacontrols.com.


    From the docs:

    Subclassing Notes
    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.

    adding text views is modifying the view hierarchy and could lead to appstore submission refusal.


    using this category you can easily inspect the view hierarchy of any view. (or use po [alertView recursiveDescription] on the debugger console)

    Note: this is code that should NEVER be used in a real world application.

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title"
                                                            message:@"msg"
                                                           delegate:nil
                                                  cancelButtonTitle:@"ok"
                                                  otherButtonTitles: nil];
    
        UITextField *textFiled = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
        [textFiled setText:@"dont try that at home"];
        [alertView addSubview:textFiled];
        [alertView show];
        [alertView printSubviewsWithIndentation:4];
    

    we will log this hierarchy

    [0]: class: 'UIImageView'
    [1]: class: 'UILabel'
    [2]: class: 'UILabel'
    [3]: class: 'UIAlertButton'
       [0]: class: 'UIImageView'
       [1]: class: 'UIButtonLabel'
    [4]: class: 'UITextField'
    

    resulting in this

    screenshot of alertview mess

    The textView is just placed over all others. actually it must be placed under [2]: class: 'UILabel'. We could do this via fiddling with the view hierarchy (loop through it and re-arrange this) or by sublassing UIAlertView and overwriting layoutSubviews. Both things, apple does not want.

    So to summarize it, if it comes to UIAlertView, you have 3 options:

    1. live with it, as it is (remember, some forms of input are available via the predefined styles)
    2. use some other view controller to present a modal view
    3. use a replacement. but one that does not subclass UIAlertView.


    But if someone is still convinced that messing around with the view hierarchy IS a good idea and knows better than me and apple's engineers, here is the code

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title"
                                                        message:@"Please read carefully the next 3 lines"
                                                       delegate:nil
                                              cancelButtonTitle:@"ok"
                                              otherButtonTitles: nil];
    
    [alertView show];
    
    
    CGFloat height = 25.0;
    
    UILabel *msgLabel = [[alertView subviews] objectAtIndex:2];
    
    UITextField *textField1 = [[UITextField alloc] initWithFrame:CGRectMake(msgLabel.frame.origin.x, msgLabel.frame.origin.y+msgLabel.frame.size.height, msgLabel.frame.size.width, height)];
    [textField1 setText:@"dont try that at home"];
    [textField1 setBackgroundColor:[UIColor whiteColor]];
    UITextField *textField2 = [[UITextField alloc] initWithFrame:CGRectOffset(textField1.frame, 0, height + 4)];
    [textField2 setText:@"REALLY! dont try that at home"];
    [textField2 setBackgroundColor:[UIColor whiteColor]];
    
    UITextField *textField3 = [[UITextField alloc] initWithFrame:CGRectOffset(textField2.frame, 0, height + 4)];
    [textField3 setText:@"REALLY! dont try that at home"];
    [textField3 setBackgroundColor:[UIColor whiteColor]];
    
    NSArray *followringSubviews = [[alertView subviews] subarrayWithRange:NSMakeRange(3, [[alertView subviews] count] - 3)];
    [followringSubviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
        view.frame = CGRectOffset(view.frame, 0, 3*height);
    
    }];
    [alertView addSubview:textField1];
    [alertView addSubview:textField2];
    [alertView addSubview:textField3];
    
    alertView.frame = CGRectUnion(alertView.frame, CGRectOffset(alertView.frame, 0, 80));
    

    Result:

    enter image description here