iOS TextField AutoCapitalization not working - ios

I have created a new project that only has one text field and I set the capitalization to all characters. I tried this from both interface builder and code:
[self.textField setAutocapitalizationType:UITextAutocapitalizationTypeAllCharacters];
No matter what I try, this is the result:
I am aware that the keyboard Auto-Capitalization settings can be changed from Settings - General - Keyboard - Auto-Capitalization, but I assume there would be no purpose in having the AutocapitalizationType property on a text field if it is overwritten by the iOS anyway.
It is also not working for UITextAutocapitalizationTypeWords.
This is happening on iOS 10.0.2 on an iPhone 6S (other answers say that it happens in simulator, but this is not the case).
Any idea what is the issue?

I am aware that the keyboard Auto-Capitalization settings can be
changed from Settings - General - Keyboard - Auto-Capitalization, but
I assume there would be no purpose in having the
AutocapitalizationType property on a text field if it is overwritten
by the iOS anyway.
You're right, the this switch in settings should be on. But it does not override the value of textfields in an app. If this toggle is on, all textfields which want to capitilize user's input will be allowed to do so and textfields with UITextAutocapitalizationTypeNone value won't capitalize anything.

One way I enforced an all-caps presentation in textField regardless of the autocapitalization directive, was to insert this little twist in the UITextFieldDelegate func:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let str = string.capitalized
let result = (textField.text as NSString?)?.replacingCharacters(in: range, with: str) ?? str
textField.text = result
return false
}
This will capitalize inserted characters too, as expected.

Related

How can i disable input textfield from user with only One-Time-Code auto fill support

I want to disable manual text entering from one-time-code textField while the user only can tap SMS OTP Code from Keyboard Quicktype Bar.
Another question i got from seeing whatsapp is that their input shows the Keyboard Quicktype bar automatically while mine is not unless i call becomeFirstResponder
How can i achieve this?
Thanks.
You can try this, maybe it works for your use case
Remove textField.isEnabled = false if you added it before
Add textField.delegate = self so we can manage what happens when user adds input
Add textField.becomeFirstResponder() to make the keyboard appear
Then implement this UITextFieldDelegate callback
extension YourViewOrViewController: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
// Only allow multiple characters to be set like the OTP
// Or define your own logic when you want text to be
// accepted into the text field
return string.count != 1
}
}
Check if this gives you the desired result

iOS: when user select QuickType keyboard handle selected UITextField

In my project when user select specific UITextField (that UITextField supposed to get user telephone number), the QuickType Keyboard show user telephone number. I want when user select his/her telephone number I can change that (remove "+" in telephone number) and show the result in that UITextField. how can I do that?
UPDATE:
I tried shouldChangeCharactersIn (UITextFieldDelegate function) to handle that, but replacementString return space (" ") and if I just return true (doing nothing inside that function) to that nothing will show inside UITextField.
You were on the right track with shouldChangeCharactersIn, but in case with QuickType keyboard it gets called two times instead of one.
First call is made to clean the current string, even when it's empty: range is (0, 0) in this case. Not much sence, but if you type something, select whole text, and paste phone number from quick help, this first change will have range of the full string to clear it.
And to modify input string, you need to update text field text and return false, because you don't need system to update text anymore.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.starts(with: "+") {
let modifierString = String(string.dropFirst())
.trimmingCharacters(in: .whitespacesAndNewlines)
textField.text = ((textField.text ?? "") as NSString)
.replacingCharacters(in: range, with: modifierString)
return false
} else {
return true
}
}
Note that it'll also ignore press of "+" made by user, if you don't want that you probably need to add more logic to that if, like
if string.count > 1 && string.starts(with: "+") {
This will allow user to press "+" but remove it from any pasted content.
If your objective is to remove any extra characters and keep only numbers, you could in the first place restrict the user to inputting only numbers by selecting the "Number Pad" keyboard type in the attributes inspector of the text field in the storyboard.
Or if you'd like to do it with code:
textField.keyboardType = .numberPad
Sorry if this is not what you are looking for, I just thought maybe you overcomplicated the problem and resorted to filtering the text to numbers, when there is an Apple-provided type of keyboard exactly for collecting phone numbers that you could use instead.

iOS autofill assumes the field before password is the username

The autofill works incredibly well, but I have one scenario when it isn't optimal and I am not aware of a work around a perhaps a proper way of doing it.
I have a screen with 2 UITextFields, first one is Amount, a monetary value to be transferred to another person. The second field is the password, the user will need to re-enter his password before the transaction can be completed.
The first field (Amount) has content type set as .unspecified and the second field (password) has it set to .password
When the user taps the second field Autofill beautifully suggest the the password to be used, but once the correct password is tapped, iOS automatically assumes the first field (amount) is the username and fills it with the username associated with the selected account, overwriting the amount the user had previously entered.
Is there a way to force password only autofill?
Today i face the same issue, with some different way. My situation is taking input of mobile number and password entry into the login page. Native app only support for mobile number while the web app support for email only. So while iOS autofill is in action, it fill the mobile number field with the email field, which is not acceptable.
After playing sometime with the autofill, i have found the life-cycle of the UITextField delegate is somewhat different in case of autofill.
When a autofill is tapped which is provided in the top of the keyboard, the UITextFieldDelegate start working from the beginning. Although the keyboard is open the delegate method started from the current with call order as follows
textField(_:shouldChangeCharactersIn:replacementString:)
textFieldShouldEndEditing(_:)
This delegate calls without the keyboard dismissing and re-appear again. This is unusual. Returning false in the textField(_:shouldChangeCharactersIn:replacementString:) has no effect in this case.
So theoretically i have the chance to edit the mobile field in the textFieldShouldEndEditing. To do that i keep track of the text which was present before the autofill begin. so took two variable as follows
var previousText: String?
var nextText: String?
Whenever a UITextField begin editing, i save it in previousText as following
public func textFieldDidBeginEditing(_ textField: UITextField) {
previousText = textField.text
}
then i track the changes inside the textField(_:shouldChangeCharactersIn:replacementString:) as following
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
nextText = self.getCompleteString(original: textField.text, replacingRange: range, withString: string)
// YOU MAY RETURN `true` OR `false` BASED ON KEYBOARD TYPING, BUT RETURNING `false` IN CASE OF AUTOFILL HAS NO EFFECT. SO I ASSUME, YOU RETURN `true` ALWAYS.
return true;
}
func getCompleteString(original: String?, replacingRange: NSRange, withString: String) -> String? {
guard var originalText = original else {
return nil
}
guard let range = Range<String.Index>.init(replacingRange, in: originalText) else {
return nil
}
originalText.replaceSubrange(range, with: withString)
return originalText
}
Now the most interesting part, detecting custom requirement (in my case detecting a possible valid mobile number, where your case was detecting a valid amount)
func textFieldDidEndEditing(_ textField: UITextField) {
if textField == MY_MOBILE_TEXT_FIELD {
if nextText.IS_POSSIBLE_VALID_MOBILE_NUMBER() { // my function to detect the possible valid mobile number
textField.text = nextText
} else {
textField.text = previousText
}
}
}
It worked for me, hope it works for you too.
Autofill disregards what textfield delegate methods return
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
So can try another hack which worked for me,
You can set textContentType of amount text field to password type and use a toolbar on the keyboard to side autofill suggestions(Since you would be using num pad for entering digits in the amount field so you might already be using a custom toolbar).
amount_text_field.textContentType = .password
This way, iOS will assume it to be a password textfield and would not fill usernames or passwords which were applied from other textfields. And using toolbar should help you hide autofill suggestions on this textfield.

UItextField restrict user to enter number only IOS app on ipad

I'm developing an app for Ipad. I'm designing a forgot password screen to allow user to enter password to UITextField. By design, the password only allow numeric input. I can set UITextFiled keyboardtype to be phonepad in Iphone but the option seem not working for Ipad (Ipad always show the full keyboard layout). How can we achieve the keyboard for Ipad app that only have number?
Do I have to design my own keyboard layout?
Any help is much appreciate. Thanks!
The keyboard type does not dictate what sort of input the textfield accepts, even if you use a custom keyboard that only displays numbers, the user can always paste something or use an external hardware keyboard.To do that, you need to observe the input, for example, by becoming the UITextFieldDelegate and then:
Example in swift:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
// non decimal digit character set, better save this as a property instead of creating it for each keyboard stroke
let non_digits = NSCharacterSet.decimalDigits.inverted
// Find location for non digits
let range = string.rangeOfCharacter(from: non_digits)
if range == nil { // no non digits found, allow change
return true
}
return false // range was valid, meaning non digits were found
}
This will prevent any non digit character from being added to the textfield.
There is not a built in number-only (phone/pin) keyboard on iPad
You need to implement your own keyboard if you want this on iPad.
There are many examples out there:
https://github.com/azu/NumericKeypad
https://github.com/lnafziger/Numberpad
https://github.com/benzado/HSNumericField
Yes I was facing the same for iPad hence I used this:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// to avoid any other characters except digits
return string.rangeOfCharacter(from: CharacterSet(charactersIn:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!##$%^&*()-=_+`~[{]}|\\: ;\"/?>.<,'")) == nil
}

Narrowing Down UITextField on BackSpace while typing

Using Storyboard, I setup a UITextField and two static UILabels. I setup the constraints so the static labels spread out as user types in the TextField.
[Label1] [TextField] [Label2]
[Label1] [TextFieldIsGettingFilled] [Label2]
Everything is fine until now. The TextField is getting wider as user types in. However, if the user uses backspace (deletes character), TextField doesn't get narrower. So it becomes like:
[Label1] [TextField ] [Label2]
What is the way of detecting backspace and narrow TextFields' width accordingly while user is still typing?
EDIT
I made an example and this works (increases and decreases according to text):
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
textField.invalidateIntrinsicContentSize()
return true
}
Source: Resize a UITextField while typing (by using Autolayout)

Resources