I have several text fields in one view controller and I'm using the following function to limit the number of characters:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return textView.text.characters.count + (text.characters.count - range.length) <= 300
}
How can I change the number of maximum number of characters for a different text field? I need a lower limit for another text field.
For TextView you need to use following TextView delegate method
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
{
if textView == yourTextViewName
{
let str = (NSString(string: textView.text!)).replacingCharacters(in: range, with: text)
if str.characters.count <= 300 {
return true
}
textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 300))
return false
}
return true
}
For TextField you have to use following delegate method
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
if textField == yourTextFieldName {
let str = (NSString(string: textField.text!)).replacingCharacters(in: range, with: string)
if str.characters.count <= 300 {
return true
}
textField.text = str.substring(to: str.index(str.startIndex, offsetBy: 300))
return false
}
return true
}
I hope this help you.
Related
I am using phone number texfield, now i am using this format for texfield (#) ### ### ###, now issue is that i want first character 0 as compulsary, like this (0) 959 554 545, so user enter whatever first character must be typed 0,
this is my code
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newString = textField.text
if ((newString == "") && (newString?.count == 0)){
txtMobileNumber.text = "0"
return true
}else if ((newString?.count)! > 0){
return true
}
return false
}
In shouldChangeCharactersIn method return false if new string count is greater than 15. Else remove (0) and empty spaces, then if the string isn't empty add (0) at the beginning. Then split the string by every 3 characters and join all string with space separator.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var oldText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
if oldText.count > 15 { return false }
oldText = oldText.replacingOccurrences(of: "(0)", with: "").replacingOccurrences(of: " ", with: "")
if !oldText.isEmpty {
oldText = "(0)" + oldText
}
let newText = String(stride(from: 0, to: oldText.count, by: 3).map {
let sIndex = String.Index(encodedOffset: $0)
let eIndex = oldText.index(sIndex, offsetBy: 3, limitedBy: oldText.endIndex) ?? oldText.endIndex
return String(oldText[sIndex..<eIndex])
}.joined(separator: " "))
textField.text = newText
return false
}
In shouldChangeCharactersIn method of UITextFieldDelegate,
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
let str = (text as NSString).replacingCharacters(in: range, with: string).replacingOccurrences(of: "(0)", with: "")
if !str.isEmpty {
textField.text = "(0)" + str
} else {
textField.text = nil
}
}
return false
}
Append (0) to the newly created string, everytime the textField is edited.
If you create Enum, you can choice your textField type and make the extension properties for this field
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
if cellType == .phone {
guard var sanitizedText = textField.text else { return true }
if !sanitizedText.isEmpty && !sanitizedText.hasPrefix("(0)") {
sanitizedText.text = "(0)" + sanitizedText
}
}
}
I am looking to cap the amount of characters a user can type into a textfield at 14. Here is the code that I have found documentation on.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let currentCharacterCount = userNameTextField.text?.characters.count ?? 0
if (range.length + range.location > currentCharacterCount){
return false
}
let newLength = currentCharacterCount + string.characters.count - range.length
return newLength <= 14
}
but I do not feel that I am implementing this correctly. I have set
userNameTextField.delegate = self
in the viewDidLoad, and I am conforming to the UITextFieldDelegate protocol.
You state you are using Swift 3. The signature of many methods changed in Swift 3. You need to use:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
}
Not the old signature posted in your question.
If it's still not being called, then you never set the text field's delegate property.
Try this instead:
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
let currentString: NSString = (textField.text ?? "") as NSString
let newString = currentString.replacingCharacters(in: range, with: string)
return newString.characters.count <= 14
}
Try this for swift 3:
let limit=4;
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = txtSMSCode.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= limit
}
I am trying to limit the number of characters inside the text view to 20. After 20 it should instead have "...". The function is not firing and I am setting the delegate correctly.
Animal class
cell.pn.text = np[indexPath.row]
cell.pn.selectable = false
cell.pn.delegate = self
Extension of Animal class
extension Animal : UITextViewDelegate{
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
return textView.text.characters.count + (text.characters.count - range.length) <= 20
}
}
Try this:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let text = textField.text
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= 20
}
You can use something like this:
if displayName.characters.count > 20 {
displayName = (displayName as NSString).substringToIndex(20)
displayName.appendContentsOf("...")
}
I want to restrict the use of the spacebar in the beginning of the textfield in iOS. I tried to use the below logic but it is not allowing spaces anywhere between the words. Please help me in this case.
if self.rangeOfCharacterFromSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) != nil {
return false
}
return true
For TextField
Swift 5.2, Xcode 11.4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard range.location == 0 else {
return true
}
let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) as NSString
return newString.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines).location != 0
}
If you need to do what you described, you can use the textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) method in UITextViewDelegate.
Example:
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
// as #nhgrif suggested, we can skip the string manipulations if
// the beginning of the textView.text is not touched.
guard range.location == 0 else {
return true
}
let newString = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text) as NSString
return newString.rangeOfCharacterFromSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).location != 0
}
First, we construct the new string that will be shown in the textView.
And then we check if it start with a whitespace, tab or newline character.
If so, we return false so the the textView won't place the new text in.
Otherwise, put the new text into the textView.
Note: We need to check the whole string instead of checking the replacementText to deal with copy-paste actions.
Another possible way is not restricting the text the user typed, but trimming the result text when you need to use the value.
let myText = textView.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
Edit: add a guard clause to make the method more performant based on #nhgrif's comment.
Write this in textView delegate:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard range.location == 0 else {
return true
}
let newString = (textView.text as NSString).replacingCharacters(in: range, with: text) as NSString
return newString.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines).location != 0
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (range.location == 0 && string == " ") {
return false
}
}
Swift 4.1
Just simple with Single line of code you can stop whitespace
For All UITextView
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
textView.text = textView.text.replacingOccurrences(of: " ", with: "")
}
For Single UITextView
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if textView == textViewArea
{
textView.text = textView.text.replacingOccurrences(of: " ", with: "")
}
return true
}
Here improvement in Answer You can disable blankSpaces until your First Character Enter
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
let whitespaceSet = NSCharacterSet.whitespaces
let range = text.rangeOfCharacter(from: whitespaceSet)
if let _ = range {
let txt = textView.text ?? ""
if txt.isBlankByTrimming || txt.isEmpty {
return false
}else {
return true
}
}
else {
return true
}
}
After this before saving your final string you Can trim Spaces and newline from End Of the string .
Example : "MyName Surname "
extension String {
var isBlankByTrimming: Bool {
let trimmed = self.trimmingCharacters(in:
CharacterSet.whitespacesAndNewlines)
return trimmed.isEmpty
}
func trimWhitespacesAndNewlines() -> String{
return self.trimmingCharacters(in:
CharacterSet.whitespacesAndNewlines)
}}
for use ::
let yourString = "MyName Surname "
let finalString = yourString.trimWhitespacesAndNewlines()
//User never input space in text field(swift 5)...
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == " " {
// If consecutive spaces entered by user
return false
}
}
I want to restrict my textview to 50 characters. I did it, but I am unable to press backspace after 50 characters. How to solve the problem ? My code is as below (Note: 'txtv' is my textview name)
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if (self.txtv.text.characters.count) >= 50 {
return false
}
return true
}
if users cutting text, or deleting strings longer than a single character (ie if they select and then hit backspace), do like this
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
return textView.text.characters.count + (text.characters.count - range.length) <= 50
}
You haven't check incoming text, you should do that before before limiting text input.
if text.characters.count == 0 { // if backspace
return true
}
if (self.txtv.text.characters.count) >= 50 {
return false
}
return true
}