I needed to display a password prompt in Delivery Status touch and quickly found that there was no ideal way to do it. There are some unsupported methods, but the workaround below—adding a UITextField as a subview of the alert—is the proper method for a third party app, according to Apple.
Aside from the basic technique of adding a UITextField as a subview, there are two other things I struggled with. First, if the text given for the message was too long it would wrap to a second line and appear partially underneath the text field. I worked around this problem by adding my own UILabel subview. The custom label is a single line so you’ll get the standard ellipsis (…) if the text is too long. For the message text I just supply three blank lines, which makes the alert large enough to display the contents. It’s a clunky way to resize the alert, but it works.
The other thing I struggled with was getting the text field to match what Apple uses. The standard beveled edge looks okay, but Apple’s own password prompts have a field that’s customized specifically for alerts. My solution was to insert an image, and display the text field, without a border, on top of it. Here’s the image I’m using.
Using those tricks, here’s the complete code I’m using to display a password prompt:
12345678910111213141516171819202122232425262728293031 UIAlertView *passwordAlert = [[UIAlertView alloc] initWithTitle:@“Server Password” message:@”nnn”delegate:self cancelButtonTitle:NSLocalizedString(@“Cancel”,nil) otherButtonTitles:NSLocalizedString(@“OK”,nil), nil];UILabel *passwordLabel = [[UILabel alloc] initWithFrame:CGRectMake(12,40,260,25)];passwordLabel.font = [UIFont systemFontOfSize:16];passwordLabel.textColor = [UIColor whiteColor];passwordLabel.backgroundColor = [UIColor clearColor];passwordLabel.shadowColor = [UIColor blackColor];passwordLabel.shadowOffset = CGSizeMake(0,-1);passwordLabel.textAlignment = UITextAlignmentCenter;passwordLabel.text = @“Account Name”;[passwordAlert addSubview:passwordLabel];UIImageView *passwordImage = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@“passwordfield” ofType:@“png”]]];passwordImage.frame = CGRectMake(11,79,262,31);[passwordAlert addSubview:passwordImage];UITextField *passwordField = [[UITextField alloc] initWithFrame:CGRectMake(16,83,252,25)];passwordField.font = [UIFont systemFontOfSize:18];passwordField.backgroundColor = [UIColor whiteColor];passwordField.secureTextEntry = YES;passwordField.keyboardAppearance = UIKeyboardAppearanceAlert;passwordField.delegate = self;[passwordField becomeFirstResponder];[passwordAlert addSubview:passwordField];[passwordAlert setTransform:CGAffineTransformMakeTranslation(0,109)];[passwordAlert show];[passwordAlert release];[passwordField release];[passwordImage release];[passwordLabel release];
You can see the result of this code in the screenshot above. It can be customized fairly easily, if you need another type of text entry, more lines of text, or some other change. (Remove the secureTextEntry line or change the keyboardAppearance to customize the text entry field.)
I spent quite a bit of time getting it as pixel-perfect as possible. The only real difference is that it’s a few pixels taller than Apple’s, because of the imprecise way I’m sizing the alert. I think it’s fair to say most people would never notice! I’d love to see a more simplified, official method for creating these alerts, but in the meantime I’m pretty pleased with this solution. If you have any suggestions for improvements, let me know in the comments!
Update: Chris Garman sent me an email to let me know there’s a simpler way to get a good looking text entry field:
Remove the image, and the font and backgroundColor assignments.
Add passwordField.borderStyle = UITextBorderStyleRoundedRect;
This won’t look exactly the same as the dialogs that Apple uses, but it is a nice looking, simpler alternative!