如何获取 UITextView 中光标之前的字符?
How to get the Character that is before the cursor in a UITextView?
假设我有以下 UITextView
对象:
var textView = UITextView()
textView.text = "Hello World!"
现在假设我不想让用户在编辑时删除 "W" 字符。我怎么知道哪个字符在光标之前(或被光标选中)?
我正在寻找可以像这样工作的东西:
if textView.characterBeforeCursor() != "W" {
textView.deleteBackward()
}
或...(当用户选择 "W" 字符时):
if textView.selectedTextContains("W") == false {
textView.deleteBackward()
}
我应该使用什么方法来完成这个?
这是一个想法,尚未经过全面测试,但似乎可行...只需抓住要操作的角色并阻止退格键(如果它是目标)...还有关于文本选择,如果选择完全包含目标,我们阻止新文本。
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
}
}
}
应该这样做:
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)
}
在上面的代码中 let txt = textView.text
只是为了简单起见,我们可以保持强制展开 textView.text!
因为 .text
属性 从来没有被设计 returns nil
对于非零 UITextView。
通过 let txtRange = Range(range, in: txt)
我们得到一个 Range<String.Index>
类型的变量,而不是 range
的普通 NSRange。这样我们就可以得到textView即将变化的txt
的Substring。
最后返回检查subString
是否包含forbiddenLetter
的结果。
此代码段将通过以下方式阻止删除 W
:
- 退格键 ⌫
- 正在删除选择
- 粘贴选择
- 自动更正(从弹出窗口)
假设我有以下 UITextView
对象:
var textView = UITextView()
textView.text = "Hello World!"
现在假设我不想让用户在编辑时删除 "W" 字符。我怎么知道哪个字符在光标之前(或被光标选中)?
我正在寻找可以像这样工作的东西:
if textView.characterBeforeCursor() != "W" {
textView.deleteBackward()
}
或...(当用户选择 "W" 字符时):
if textView.selectedTextContains("W") == false {
textView.deleteBackward()
}
我应该使用什么方法来完成这个?
这是一个想法,尚未经过全面测试,但似乎可行...只需抓住要操作的角色并阻止退格键(如果它是目标)...还有关于文本选择,如果选择完全包含目标,我们阻止新文本。
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
}
}
}
应该这样做:
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)
}
在上面的代码中 let txt = textView.text
只是为了简单起见,我们可以保持强制展开 textView.text!
因为 .text
属性 从来没有被设计 returns nil
对于非零 UITextView。
通过 let txtRange = Range(range, in: txt)
我们得到一个 Range<String.Index>
类型的变量,而不是 range
的普通 NSRange。这样我们就可以得到textView即将变化的txt
的Substring。
最后返回检查subString
是否包含forbiddenLetter
的结果。
此代码段将通过以下方式阻止删除 W
:
- 退格键 ⌫
- 正在删除选择
- 粘贴选择
- 自动更正(从弹出窗口)