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("...")
}
Related
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.
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 have two identical functions in my ViewController and it seems that neither of them can be renamed.
The first one is used to limit characters and show the number left.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let textField = textField as? UITextField {
if (range.length + range.location > textField.text!.characters.count) {
return false;
}
let newLength = textField.text!.characters.count + string.characters.count - range.length;
cLabel.text = String(25 - newLength)
return newLength <= 25 // To just allow up to … characters
}
return true;
}
The second one enables a button when text is added to the same textField.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (ahskField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
if text.isEmpty{//Checking if the input field is not empty
ahskButton.userInteractionEnabled = false //Enabling the button
ahskButton.enabled = false
} else {
ahskButton.userInteractionEnabled = true //Disabling the button
ahskButton.enabled = true
}
// Return true so the text field will be changed
return true
}
Is there a way to combine them or anything?
You only need one of the shouldChangeCharactersInRange functions.
Put all of your logic in the one method.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
let newLength = text.characters.count
if newLength <= 25 {
cLabel.text = String(25 - newLength)
if text.isEmpty { //Checking if the input field is not empty
ahskButton.userInteractionEnabled = false //Enabling the button
ahskButton.enabled = false
} else {
ahskButton.userInteractionEnabled = true //Disabling the button
ahskButton.enabled = true
}
return true;
} else {
return false;
}
}
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 have a UITextField that I want to limit the lenght to 4 characters here's the code for it :
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let text = acRegTextField.text else { return true }
let newLength = text.utf16.count + string.utf16.count - range.length
return newLength <= 4 // Bool
}
problem is, with this code, my other text box gets stopped when acRegTextField as 4 char in it.
I honestly don't get it... any help would be appreciated
thanks
If you have numerous textfields on your view and assign the delegate to them then shouldChangeCharactersInRange will apply to all the textfields. So what you can do is if you already have an outlet to the textfield that should contain just 4 characters - then just compare this textfield is the one you want to validate - note the === compares the reference. eg:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if acRegTextField === textField {
guard let text = acRegTextField.text else { return true }
let newLength = text.utf16.count + string.utf16.count - range.length
return newLength <= 4 // Bool
}
return true
}
This is a method from UITextFieldDelegate. To make this work, you must have said somewhere
myTextField.delegate = myClass
Every text field you say that for will get the same delegate. If you don't want the limit to apply to a particular textField, then don't set the delegate for that textField.