allowing backspace in textview in swift 2 - ios

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
}

Related

How to limit the amount of lines a user has using return?

In this project, users have the ability to write a bio with a character limit of 150. Is it also possible to limit the number of lines a user can have? For example when I press return on the keyboard, it creates a new line. And I can do that as many times as I like, can I change that?
Similar to how Instagram limits how long a bio (height wise) can be somehow while still having a character limit.
Heres the code for character limit
// Give textView character limit of 150
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if(textView.text.count > 150 && range.length == 0) {
print("Opps hit 150")
navigationItem.rightBarButtonItem?.isEnabled = false
return false
}
navigationItem.rightBarButtonItem?.isEnabled = true
return true
}
Update
Based on the answer I received, here is the updated code
var lineCounter = 0
extension EditProfileController: UITextViewDelegate {
// Give textView character limit of 150
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
// Prevent the user from creating to many new lines.
if(text == "\n") {
lineCounter += 1
if lineCounter == 20 {
}
print("Stop sending user to next line")
return false
}
if(textView.text.count > 150 && range.length == 0) {
print("Opps hit 150")
navigationItem.rightBarButtonItem?.isEnabled = false
return false
}
navigationItem.rightBarButtonItem?.isEnabled = true
return true
}
}
So the good news is when I click return it doesn't create a new line. However is it possible to allow the return button to create 4 new lines before rerunning false?
Alternate, you can take a class variable like LineCounter and inside your delegate method, you should use the below code. It will minimize the need of your requirement.
// Member variable
var lineCounter = 0
For example, you want, user can tap the Return button maximum 5 times but he can input 150 char.
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if(text == "\n") {
lineCounter += 1
if lineCounter >= 5 {
return false
}
}
if(textView.text.count > 150 && range.length == 0) {
print("Opps hit 150")
navigationItem.rightBarButtonItem?.isEnabled = false
textView.resignFirstResponder()
return false
}
navigationItem.rightBarButtonItem?.isEnabled = true
return true
}
You can calculate the height of the textView based on their font size, and check in the UITextViewDelegate if that height was reached
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
// check here
}

Limit length of several text fields

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.

How do I cut off the text view after 20 characters?

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("...")
}

How to stop the user not to type space in the beginning of the text in UITextView iOS?

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
}
}

How to limit the numbers in the text field in Swift?

I want the user to fill in the textfield a number from 0 to 60.
How can i limit the number chars to 2?
How to limit the maximum number to 60?
And how to cancel the 'paste' option on the textfield so the user won't be able to paste letters?
I think there are 2 ways you can do that.
Implement the UITextFieldDelegate and implement function
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool {
var startString = ""
if textField.text != nil {
startString += textField.text!
}
startString += string
var limitNumber = startString.toInt()
if limitNumber > 60 {
return false
} else {
return true
}
}
In this Each time check what has been entered to the UITextField so far, convert to Integer and if the new value is higher than 60, return false. (Also show the appropriate error to the user).
I think a much better way would be to provide UIPickerView.
Use textfield's delegate method
Where 10 is Max limit for text field...
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let newLength = countElements(textField.text) + countElements(string) - range.length
return newLength <= 10 // Bool
}
If countElements not work in latest version of s
wift use count instead of countElements.
To disable copy and paste:
func canPerformAction(_ action: Selector, withSender sender: AnyObject?) -> Bool
{
if action == "paste:"
{return false}
return super.canPerformAction(action,withSender:sender)
}

Resources