iOS

UITextField

Introduction#

UITextField is part of UIKit framework and is used to display an area to collect text input from the user using the onscreen keyboard

Syntax#

  • UITextField.text: String // get or set the text the field displays.
  • UITextField.attributedText: NSAttributedString // get or set the attributed text the field displays.
  • UITextField.textColor: UIColor // get or set the color of the text on the field
  • UITextField.font: UIFont // get or set the font of the text on the field
  • UITextField.textAlignment: NSTextAlignment // default is NSLeftTextAlignment
  • UITextField.borderStyle: UITextBorderStyle // default is UITextBorderStyleNone. If set to UITextBorderStyleRoundedRect, custom background images are ignored.
  • UITextField.placeholder: String // default is nil. string is drawn 70% gray
  • UITextField.attributedPlaceholder: NSAttributedString // get or set the attributed placeholder of the field
  • UITextField.clearsOnBeginEditing: Bool // default is NO which moves cursor to location clicked. if YES, all text cleared
  • UITextField.adjustsFontSizeToFitWidth: Bool // default is NO. if YES, text will shrink to minFontSize along baseline
  • UITextField.minimumFontSize: CGFloat // default is 0.0. actual min may be pinned to something readable. used if adjustsFontSizeToFitWidth is YES
  • UITextField.delegate: UITextFieldDelegate? // default is nil. weak reference
  • UITextField.clearButtonMode: UITextFieldViewMode // sets when the clear button shows up. default is UITextFieldViewModeNever
  • UITextField.leftView: UIView? // e.g. magnifying glass
  • UITextField.leftViewMode: UITextFieldViewMode // sets when the left view shows up. default is UITextFieldViewModeNever
  • UITextField.rightView: UIView? // e.g. bookmarks button
  • UITextField.rightViewMode: UITextFieldViewMode // sets when the right view shows up. default is UITextFieldViewModeNever
  • UITextField.inputView: UIView? // Presented when object becomes first responder. If set to nil, reverts to following responder chain. If set while first responder, will not take effect until reloadInputViews is called.
  • UITextField.inputAccessoryView: UIView?
  • UITextField.isSecureTextEntry : Bool // e.g If field contain confidential input like password or card number

Initialize text field

Swift

let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let textField = UITextField(frame: frame)

Objective-C

CGRect *frame = CGRectMake(0, 0, 100, 100);
UITextField *textField = [[UITextField alloc] initWithFrame:frame];

Interface Builder

You can also add a UITextField to a storyboard by dragging it from Object Library.

screenshot

Input accessory view (toolbar)

Add an accessory view above the keyboard. This is commonly used for adding next/previous buttons, or additional buttons like Done/Submit (especially for the number/phone/decimal pad keyboard types which don’t have a built-in return key).

Swift

let textField = UITextField() // initialized however

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 0)

let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)

let doneButton = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: Selector("done"))

let items = [flexibleSpace, doneButton]  // pushes done button to right side

toolbar.setItems(items, animated: false) // or toolbar.items = ...
toolbar.sizeToFit()

textField.inputAccessoryView = toolbar

Objective-C

UITextField *textField = [[UITextField alloc] init];

UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 0)];

UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done)];
NSArray *items = @[
                   flexibleSpace,
                   doneButton
                   ];

[toolbar setItems:items];
[toolbar sizeToFit];

textField.inputAccessoryView = toolbar;

Autocapitalization

Swift

textField.autocapitalizationType = .None

Objective-C

textField.autocapitalizationType = UITextAutocapitalizationTypeNone;

All options:

  • .None \ UITextAutocapitalizationTypeNone : Don’t autocapitalize anything
  • .Words \ UITextAutocapitalizationTypeWords : Autocapitalize every word
  • .Sentences \ UITextAutocapitalizationTypeSentences : Autocapitalize the first word in a sentence
  • .AllCharacters \ UITextAutocapitalizationTypeAllCharacters : Autocapitalize every letter (i.e. caps lock)

Dismiss Keyboard

Swift

Ctrl + Drag from the UItextfield in MainStoryboard to the ViewController Class and create a UITextField Outlet

enter image description here

enter image description here

enter image description here

After that select the UItextField again and Ctrl+drag in ViewController class but this time select Action connection and on storage select Did End On Exit then click connect.

in the action you just created type the name of your UItextField .resignFirstResponder()

   @IBAction func textFieldResign(sender: AnyObject) {
        yourTextFieldName.resignFirstResponder()
    }

This will take care of hiding the keyboard when pressing the return key on keyboard.

Another example of hiding the keyboard when return key is pressed:

we add UITextFieldDelegate protocol next to UIViewController

in the vieDidLoad function we add self.yourTextFieldName.delegate = self

And Finally we add this

func textFieldShouldReturn(textField: UITextField) -> Bool {
                yourTextFieldName.resignFirstResponder()
                return true
            }



  

The final code is this:

class ViewController: UIViewController, UITextFieldDelegate  {

@IBOutlet var textField: UITextField!

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
    view.endEditing(true)
    super.touchesBegan(touches, withEvent: event)
}


override func viewDidLoad() {
    super.viewDidLoad()
    self.textField.delegate = self
        }

}

Objective-C

[textField resignFirstResponder];

Set Alignment

Swift

textField.textAlignment = .Center 

Objective-C

[textField setTextAlignment: NSTextAlignmentCenter];

In the example, we have set the NSTextAlignment to center. You can also set to .Left, .Right, .Justified and .Natural.

.Natural is the default alignment for the current localization. That means for left-to-right languages (eg. English), the alignment is .Left; for right-to-left languages, it is .Right.

KeyboardType

To change the appearance of the keyboard, the following types can be set individually on every UITextFields property: keyboardType

typedef NS_ENUM(NSInteger, UIKeyboardType) {
    UIKeyboardTypeDefault,                // Default type for the current input method.
    UIKeyboardTypeASCIICapable,           // Displays a keyboard which can enter ASCII characters, non-ASCII keyboards remain active
    UIKeyboardTypeNumbersAndPunctuation,  // Numbers and assorted punctuation.
    UIKeyboardTypeURL,                    // A type optimized for URL entry (shows . / .com prominently).
    UIKeyboardTypeNumberPad,              // A number pad (0-9). Suitable for PIN entry.
    UIKeyboardTypePhonePad,               // A phone pad (1-9, *, 0, #, with letters under the numbers).
    UIKeyboardTypeNamePhonePad,           // A type optimized for entering a person's name or phone number.
    UIKeyboardTypeEmailAddress,           // A type optimized for multiple email address entry (shows space @ . prominently).
    UIKeyboardTypeDecimalPad NS_ENUM_AVAILABLE_IOS(4_1),   // A number pad with a decimal point.
    UIKeyboardTypeTwitter NS_ENUM_AVAILABLE_IOS(5_0),      // A type optimized for twitter text entry (easy access to @ #)
    UIKeyboardTypeWebSearch NS_ENUM_AVAILABLE_IOS(7_0),    // A default keyboard type with URL-oriented addition (shows space . prominently).

    UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable, // Deprecated
};

Moving scroll when UITextView becomes first responder

Observe the notifications UIKeyboardWillShowNotification and UIKeyboardWillHideNotification, update the scrollView content insets according to keyboard height, then scroll to the focused control.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
}

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }
    
    NSDictionary *userInfo = [notification userInfo];
    
    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];
    
    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];
    
    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);
    
    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    
    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;
    
    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.
        
        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;
        
        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;
        
        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);
            
            // make sure we don't set an impossible offset caused by the "nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);
            
            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.origin.y;
            
            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }
    
    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }
    
    NSDictionary *userInfo = notification.userInfo;
    
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    
    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
    
    [UIView commitAnimations];
}

Get Keyboard Focus and Hide Keyboard

Get Focus

Swift

textField.becomeFirstResponder()

Objective-C

[textField becomeFirstResponder];

Resign

Swift

textField.resignFirstResponder()

Objective-C

[textField resignFirstResponder];

Replace keyboard with UIPickerView

In some cases, you want to show your users a UIPickerView with predefined contents for a UITextField instead of a keyboard.

Create a custom UIPickerView

At first, you need a custom wrapper-class for UIPickerView conforming to the protocols UIPickerViewDataSource and UIPickerViewDelegate.

class MyPickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate

You need to implement the following methods for the DataSource and Delegate:

public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if data != nil {
        return data!.count
    } else {
        return 0
    }
}

public func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    if data != nil {
        return data![row]
    } else {
        return ""
    }
}

To handle the data, MyPickerView needs the properties data, selectedValue and textFieldBeingEdited:

/**
 The data for the `UIPickerViewDelegate`

 Always needs to be an array of `String`! The `UIPickerView` can ONLY display Strings
 */
public var data: [String]? {
    didSet {
        super.delegate = self
        super.dataSource = self
        self.reloadAllComponents()
    }
}

/**
 Stores the UITextField that is being edited at the moment
 */
public var textFieldBeingEdited: UITextField?

/**
 Get the selected Value of the picker
 */
public var selectedValue: String {
    get {
        if data != nil {
            return data![selectedRow(inComponent: 0)]
        } else {
            return ""
        }
    }
}

Prepare your ViewController

The ViewController that contains your textField, needs to have a property for your custom UIPickerView. (Assuming, that you already have another property or @IBOutlet containing your textField)

/**
 The picker view to present as keyboard
 */
var picker: MyPickerView?

In your viewDidLoad(), you need to initialize picker and configure it a bit:

picker = MyPickerView()
picker?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
picker?.backgroundColor = UIColor.white()

picker?.data = ["One", "Two", "Three", "Four", "Five"] //The data shown in the picker

Now, you can add the MyPicker as inputView of your UITextField:

textField.inputView = picker

Dismissing the picker-keyboard

Now, you have replaced the keyboard by an UIPickerView, but there is no possibility to dismiss it. This can be done with a custom .inputAccessoryView:

Add the property pickerAccessory to your ViewController.

/**
 A toolbar to add to the keyboard when the `picker` is presented.
 */
var pickerAccessory: UIToolbar?

In viewDidLoad(), you need to create an UIToolbar for the inputAccessoryView:

pickerAccessory = UIToolbar()
pickerAccessory?.autoresizingMask = .flexibleHeight

//this customization is optional
pickerAccessory?.barStyle = .default
pickerAccessory?.barTintColor = UIColor.red()
pickerAccessory?.backgroundColor = UIColor.red()
pickerAccessory?.isTranslucent = false

You should set the frame of your toolbar. To fit in the design of iOS, it’s recommended to use a height of 44.0:

var frame = pickerAccessory?.frame
frame?.size.height = 44.0
pickerAccessory?.frame = frame!

For a good user experience, you should add two buttons (“Done” and “Cancel”), but it would also work with only one that dismisses the keyboard.

let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ViewController.cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white()
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) //a flexible space between the two buttons
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ViewController.doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white()

//Add the items to the toolbar    
pickerAccessory?.items = [cancelButton, flexSpace, doneButton]

Now you can add the toolbar as inputAccessoryView

textField.inputAccessoryView = pickerAccessory

Before you can build your project, you need to implement the methods, the buttons are calling:

/**
 Called when the cancel button of the `pickerAccessory` was clicked. Dismsses the picker
 */
func cancelBtnClicked(_ button: UIBarButtonItem?) {
    textField?.resignFirstResponder()
}

/**
 Called when the done button of the `pickerAccessory` was clicked. Dismisses the picker and puts the selected value into the textField
 */
func doneBtnClicked(_ button: UIBarButtonItem?) {
    textField?.resignFirstResponder()
    textField.text = picker?.selectedValue
}

Run your project, tap the textField and you should see a picker like this instead of the keyboard:

picker example

Select a value programmatically (optional)

If you don’t want to have the first row selected automatically, you can set the selected row as in UIPickerView:

picker?.selectRow(3, inComponent: 0, animated: false) //Will select the row at index 3

Dismiss keyboard when user pushes the return button

Setup your view controller to manage editing of text for the text field.

class MyViewController: UITextFieldDelegate {

    override viewDidLoad() {
        super.viewDidLoad()
        
        textField.delegate = self
    }

}

textFieldShouldReturn is called every time the return button on the keyboard is pressed.

Swift:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()    
    return true;
}

Objective-C:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
   [textField resignFirstResponder];
   return true;
}

Getting and Setting the Cursor Position

Useful information

The very beginning of the text field text:

let startPosition: UITextPosition = textField.beginningOfDocument

The very end of the text field text:

let endPosition: UITextPosition = textField.endOfDocument

The currently selected range:

let selectedRange: UITextRange? = textField.selectedTextRange

Get cursor position

if let selectedRange = textField.selectedTextRange {
    
    let cursorPosition = textField.offsetFromPosition(textField.beginningOfDocument, toPosition: selectedRange.start)
    
    print("\(cursorPosition)")
}

Set cursor position

In order to set the position, all of these methods are actually setting a range with the same start and end values.

To the beginning

let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)

To the end

let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)

To one position to the left of the current cursor position

// only if there is a currently selected range
if let selectedRange = textField.selectedTextRange {
    
    // and only if the new position is valid
    if let newPosition = textField.positionFromPosition(selectedRange.start, inDirection: UITextLayoutDirection.Left, offset: 1) {
        
        // set the new position
        textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
    }
}

To an arbitrary position

Start at the beginning and move 5 characters to the right.

let arbitraryValue: Int = 5
if let newPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: arbitraryValue) {
    
    textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: newPosition)
}

Related

Select all text

textField.selectedTextRange = textField.textRangeFromPosition(textField.beginningOfDocument, toPosition: textField.endOfDocument)

Select a range of text

// Range: 3 to 7
let startPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 3)
let endPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 7)

if startPosition != nil && endPosition != nil {
    textField.selectedTextRange = textField.textRangeFromPosition(startPosition!, toPosition: endPosition!)
}

Insert text at the current cursor position

textField.insertText("Hello")

Notes

  • This example originally comes from this Stack Overflow answer.

  • This answer uses a text field, but the same concepts apply to UITextView.

  • Use textField.becomeFirstResponder() to give focus to the text field and make the keyboard appear.

  • See this answer for how to get the text at some range.

Related

Hide blinking caret

To hide the blinking caret, you need to override caretRectForPosition of a UITextField and return CGRectZero.

Swift 2.3 <

public override func caretRectForPosition(position: UITextPosition) -> CGRect {
    return CGRectZero 
}

Swift 3

override func caretRect(for position: UITextPosition) -> CGRect {
    return CGRect.zero
}

Objective-C

- (CGRect) caretRectForPosition:(UITextPosition*) position{
return CGRectZero;
}

Change placeholder color and font

We can change the style of the placeholder by setting attributedPlaceholder (a NSAttributedString).

var placeholderAttributes = [String: AnyObject]()
placeholderAttributes[NSForegroundColorAttributeName] = color
placeholderAttributes[NSFontAttributeName] = font

if let placeholder = textField.placeholder {
    let newAttributedPlaceholder = NSAttributedString(string: placeholder, attributes: placeholderAttributes)
    textField.attributedPlaceholder = newAttributedPlaceholder
}

In this example we change only the color and font. You could change other properties such as underline or strikethrough style. Refer to NSAttributedString for the properties that can be changed.

Create a UITextField


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow