0

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

Shmidt
  • 16,436
  • 18
  • 88
  • 136

3 Answers3

1

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

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • I'll do it. But currently I can't understand why UIAlertView frame isn't changing, even if I do [[UIAlertView alloc]initWithFrame:CGRectMake(12, 90, 260, 50)]; – Shmidt Jan 04 '13 at 20:18
  • 1
    as I said before: Apple does not want you to change the appearance. Maybe you can go around it by subclassing UIAlertView and overwrite `layoutSubviews` – vikingosegundo Jan 04 '13 at 20:20
  • You must set the new frame after calling `show`. see my *Dont try that at home* example. – vikingosegundo Jan 04 '13 at 23:21
  • @vikingosegundo the layout subviews does not seem to be invoked on iOS7 for a UIAlertView :( – yonel Apr 01 '14 at 15:11
  • @yonel, did you read the answer: **Note: this is code that should NEVER be used in a real world application.** and yes: in iOS 7 it is finally impossible, as it was always forbidden by documentation. – vikingosegundo Apr 01 '14 at 15:44
0

You want you can do this way.

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"msg" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
txtField.text=@"anoop here";
[alertView addSubview:txtField];
[alertView show];

EDIT:

Even a custom view will do your work. (as you can see in my previous edits.)

Create a custom view with custom shape size, color, text size etc, and then show it as a model window.

EDIT 2:

The above code wont run for iOS7.

Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
0

Use accessoryView property for alert view

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"change Password " message:@"" delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
     CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, 300);
     UIView *view = [[UIView alloc] initWithFrame:frame];

    UITextField* text1 = [[UITextField alloc] initWithFrame: CGRectMake(10, 10,self.view.frame.size.width-125, 30)];
    text1.backgroundColor=[UIColor whiteColor];
    UITextField* text2 = [[UITextField alloc] initWithFrame: CGRectMake(10, 45, self.view.frame.size.width-125, 30)];
    text2.backgroundColor=[UIColor whiteColor];
    UITextField* text3 = [[UITextField alloc] initWithFrame: CGRectMake(10, 80, self.view.frame.size.width-125, 30)];
    text3.backgroundColor=[UIColor whiteColor];
    text1.layer.borderColor=[UIColor lightGrayColor].CGColor;
    text1.layer.borderWidth=1;
    text2.layer.borderColor=[UIColor lightGrayColor].CGColor;
    text2.layer.borderWidth=1;
    text3.layer.borderColor=[UIColor lightGrayColor].CGColor;
    text3.layer.borderWidth=1;
    text1.placeholder=@"  Enter  old password ";
   [view addSubview:text1];
   [view addSubview:text2];
   [view addSubview:text3];
    [alertView setValue:view forKey:@"accessoryView"];
    view.backgroundColor = [UIColor whiteColor];
    [alertView show];