Reputation: 1542
Let's say I have the following UITextView
object:
var textView = UITextView()
textView.text = "Hello World!"
Now let's say I don't want to allow the user to delete the "W" character while editing it. How could I know which character is before the cursor (or selected by it)?
I'm looking for something that would work like this:
if textView.characterBeforeCursor() != "W" {
textView.deleteBackward()
}
or... (when the user selects the "W" character):
if textView.selectedTextContains("W") == false {
textView.deleteBackward()
}
What approach should I use to accomplish this?
Upvotes: 3
Views: 2578
Reputation: 18581
This should do it:
let forbiddenLetter = "W"
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard let txt = textView.text, let txtRange = Range(range, in: txt) else {
return false
}
let subString: Substring = txt[txtRange]
return !subString.contains(forbiddenLetter)
}
In the code above let txt = textView.text
is just for simplicity, we could keep force-unwrapping textView.text!
since the .text
property is designed never returns nil
for a non-nil UITextView.
By let txtRange = Range(range, in: txt)
we get a variable of type Range<String.Index>
instead of the vanilla NSRange that range
is. By doing so we can get the Substring of txt
that the textView is about to change.
Finally, the result of checking whether or not the subString
contains the forbiddenLetter
, is returned.
This snippet would prevent deleting W
by using:
Upvotes: 1
Reputation: 22926
Here's an idea, not fully tested, but seems to work... Just grab the character about to be acted upon and block backspace if its the target... Also with regard to selection of text, if the selection contains the target at all, we block new text.
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.textView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
func characterBeforeCursor() -> String? {
// get the cursor position
if let cursorRange = textView.selectedTextRange {
// get the position one character before the cursor start position
if let newPosition = textView.position(from: cursorRange.start, offset: -1) {
let range = textView.textRange(from: newPosition, to: cursorRange.start)
return textView.text(in: range!)
}
}
return nil
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (characterBeforeCursor() == "W") {
let char = text.cString(using: String.Encoding.utf8)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
return false
}
return true
}
else {
if let range = textView.selectedTextRange {
let selectedText = textView.text(in: range)
if (selectedText!.contains("W")) {
return false
}
}
return true
}
}
}
Upvotes: 4