Note that there are some explanatory texts on larger screens.

plurals
  1. POkeyboard in UIActionSheet does not type anything
    primarykey
    data
    text
    <p>I'm wondering why my iPhone keyboard opened by a UITextField doesn't type anything except the delete key and the clear button within the text field itself. The text field is embedded in a UIActionSheet with this code sample:</p> <pre><code>// setup UITextField for the UIActionSheet UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)]; NSString* startText = [[self.pathName lastPathComponent] stringByDeletingPathExtension]; textField.borderStyle = UITextBorderStyleRoundedRect; textField.backgroundColor = [UIColor whiteColor]; textField.clearButtonMode = UITextFieldViewModeAlways; textField.text = startText; textField.delegate = self; [textField setKeyboardType:UIKeyboardTypeAlphabet]; [textField setKeyboardAppearance:UIKeyboardAppearanceAlert]; // setup UIActionSheet UIActionSheet* asheet = [[UIActionSheet alloc] initWithTitle: @"Please enter file name\n\n\n" delegate: self cancelButtonTitle: @"Cancel" destructiveButtonTitle: nil otherButtonTitles: @"OK", nil]; if ([currentView isKindOfClass:[UIToolbar class]]) [asheet showFromToolbar:(UIToolbar*)currentView]; else if ([currentView isKindOfClass:[UITabBar class]]) [asheet showFromTabBar:(UITabBar*)currentView]; else [asheet showInView:currentView]; [asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 380.0)]; [asheet insertSubview:textField atIndex:0]; [textField becomeFirstResponder]; // memory management [textField release]; [asheet release]; </code></pre> <p>I can press the shift key but the keys don't change to lowercase, they are always uppercase. Well, I have never used a text field with an action sheet ... what am I doing wrong here? The delegate methods for action sheet and text field seem to be present as needed. </p> <p><strong>Edit:</strong> I've changed the view association of the action sheet and the size of the action sheet as well:</p> <pre><code>UIWindow* appWindow = [UIApplication sharedApplication].keyWindow; [asheet showInView:appWindow]; [asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)]; while (CGRectEqualToRect(asheet.bounds, CGRectZero)) ; // Add the text field to action sheet [asheet addSubview:textField]; [textField release]; </code></pre> <p>Now the keyboard is not overlapped (or "underlapped") by the action sheet, the action sheet shows properly below status bar and navigation bar and the keyboard follows below the action sheet and comes from bottom up.</p> <p>But only <strong>textFieldShouldBeginEditing</strong> and <strong>textFieldDidBeginEditing</strong> get called of the text field's delegate methods, nothing more. The shift key changes when I tap it, the erase key works, all other keys show themselves on tap - but don't insert into the text field. So, what is it all about? </p> <p><strong>Solution:</strong> Thanks to SVD pointing me to the fact that it doesn't seem to be possible to embed a UITextField into a UIActionSheet. Because I want to have a method that returns a file name string with an action sheet (just because I like the appearance more than a UIAlertView with a text field added) I've spent some more work on it and finally found a working solution. I share it here because I realized that quite a lot of you were looking for a similar thing.</p> <p>There are two main aspects to consider to get this working:</p> <ul> <li><p>the text field must not be a subview of the action sheet, at least at the moment when it is in editable state</p></li> <li><p>the action sheet should not overlap the keyboard</p></li> </ul> <p>Ok, here comes the code. The modal solution works with a second runloop, so the delegate methods for text field and action sheet can be handled w/out returning to the caller - I'm sure this can be broken down into the conventional approach where you handle all delegate stuff within your own class.</p> <p>ModalAction.h:</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @interface ModalAction : NSObject + (NSString*)ask: (NSString*)question withTextPrompt: (NSString*)prompt textPreset: (NSString*)preset dockToView: (UIView*)toView; @end </code></pre> <p>ModalAction.m:</p> <pre><code>#import "ModalAction.h" #define TEXT_FIELD_TAG 9999 #define ACTION_SHEET_TAG 8888 @interface ModalActionDelegate : NSObject &lt;UIActionSheetDelegate, UITextFieldDelegate&gt; { CFRunLoopRef currentLoop; NSString* text; NSUInteger index; } @property (assign) NSUInteger index; @property (retain) NSString* text; @end @implementation ModalActionDelegate @synthesize index; @synthesize text; -(id)initWithRunLoop: (CFRunLoopRef)runLoop { if (self = [super init]) currentLoop = runLoop; return self; } // Activate keyboard - (void)acceptInput: (UIActionSheet*)actionSheet { UITextField* textField = (UITextField*)[actionSheet viewWithTag:TEXT_FIELD_TAG]; UIWindow* appWindow = [UIApplication sharedApplication].keyWindow; CGRect frame = textField.frame; [appWindow insertSubview:textField aboveSubview:actionSheet]; frame.origin.y += 60.0; // move text field to same position as on action sheet textField.frame = frame; [textField becomeFirstResponder]; } - (void)dealloc { self.text = nil; [super dealloc]; } #pragma mark - #pragma mark === UIActionSheetDelegate === #pragma mark - // User pressed button. Retrieve results - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { NSLog(@"actionSheet clickedButtonAtIndex:%d", buttonIndex); UIWindow* appWindow = [UIApplication sharedApplication].keyWindow; UITextField* textField = (UITextField*)[appWindow viewWithTag:TEXT_FIELD_TAG]; if (textField != nil) self.text = textField.text; self.index = buttonIndex; CFRunLoopStop(currentLoop); } #pragma mark - #pragma mark === UITextFieldDelegate === #pragma mark - - (BOOL)textFieldShouldBeginEditing:(UITextField*)textField { NSLog(@"textFieldShouldBeginEditing"); return YES; } - (void)textFieldDidBeginEditing:(UITextField*)textField { NSLog(@"textFieldDidBeginEditing"); [textField becomeFirstResponder]; } - (BOOL)textFieldShouldEndEditing:(UITextField*)textField { NSLog(@"textFieldShouldEndEditing"); return YES; } - (void)textFieldDidEndEditing:(UITextField*)textField { NSLog(@"textFieldDidEndEditing"); [textField resignFirstResponder]; } - (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string { return YES; } - (BOOL)textFieldShouldClear:(UITextField*)textField { NSLog(@"textFieldShouldClearEditing"); return YES; } - (BOOL)textFieldShouldReturn:(UITextField*)textField { NSLog(@"textFieldShouldReturn (%@)", textField.text); BOOL hasSomeText = ![textField.text isEqualToString:@""]; if (hasSomeText) { // send an OK to the action sheet UIWindow* appWindow = [UIApplication sharedApplication].keyWindow; UIActionSheet* actionSheet = (UIActionSheet*)[appWindow viewWithTag:ACTION_SHEET_TAG]; if (actionSheet != nil) { [actionSheet dismissWithClickedButtonIndex:0 animated:YES]; self.text = textField.text; self.index = 0; CFRunLoopStop(currentLoop); [textField resignFirstResponder]; } } return hasSomeText; } @end @implementation ModalAction + (NSString*)textQueryWith: (NSString*)question prompt: (NSString*)prompt textPreset: (NSString*)preset button1: (NSString*)button1 button2: (NSString*)button2 forView: (UIView*)toView { // Create action sheet CFRunLoopRef currentLoop = CFRunLoopGetCurrent(); ModalActionDelegate* madelegate = [[ModalActionDelegate alloc] initWithRunLoop:currentLoop]; NSString* sheetTitle = [question stringByAppendingString:@"\n\n\n"]; UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle: sheetTitle delegate: madelegate cancelButtonTitle: button1 destructiveButtonTitle: nil otherButtonTitles: button2, nil]; actionSheet.tag = ACTION_SHEET_TAG; // Build text field UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)]; textField.borderStyle = UITextBorderStyleRoundedRect; textField.tag = TEXT_FIELD_TAG; textField.placeholder = prompt; textField.text = preset; textField.delegate = madelegate; textField.clearButtonMode = UITextFieldViewModeWhileEditing; textField.keyboardType = UIKeyboardTypeAlphabet; textField.keyboardAppearance = UIKeyboardAppearanceAlert; textField.autocapitalizationType = UITextAutocapitalizationTypeWords; textField.autocorrectionType = UITextAutocorrectionTypeNo; textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; textField.returnKeyType = UIReturnKeyDone; // Show action sheet and wait for it to finish displaying UIWindow* appWindow = [UIApplication sharedApplication].keyWindow; [actionSheet showInView:appWindow]; [actionSheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)]; while (CGRectEqualToRect(actionSheet.bounds, CGRectZero)) ; // Add the text field to action sheet [actionSheet addSubview:textField]; [textField release]; // Set the field to first responder and move it into place [madelegate performSelector: @selector(acceptInput:) withObject: actionSheet]; // Start the run loop CFRunLoopRun(); // Retrieve the user choices NSUInteger index = madelegate.index; NSString* answer = [[madelegate.text copy] autorelease]; if (index == 1) answer = nil; // assumes cancel in position 1 [textField resignFirstResponder]; [actionSheet release]; textField.delegate = nil; [textField removeFromSuperview]; [madelegate release]; return answer; } + (NSString*)ask: (NSString*)question withTextPrompt: (NSString*)prompt textPreset: (NSString*)preset dockToView: (UIView*)toView { return [ModalAction textQueryWith: question prompt: prompt textPreset: preset button1: NSLocalizedString(@"AlertBtnCancel", @"") button2: @"OK" forView: toView]; } @end </code></pre> <p>It is running on Simulator iOS 4.2 and on real devices' iOS 4.0.2 - I hope it is also helpful for others.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload