当 UITextView 上的文本更改时是否有委托调用?

问题描述 投票:0回答:8

当我像这样以编程方式设置我的

UITextView
时:

[self.textView setText:@""];

委托方法

textViewDidChange:
不会被调用。 有没有办法我可以找到而不创建
UITextView
子类?

ios cocoa-touch uitextview uitextviewdelegate
8个回答
31
投票

使用代码手动设置

UITextView
的文本时,不会调用
textViewDidChange:
方法。 (如果您设置了文本视图的
delegate
,那么当用户编辑它时它会被调用。)

一种可能的解决方法是在编辑文本时手动调用

textViewDidChange:
。例如:

[self.textView setText:@""];
[self textViewDidChange:self.textView];

有点黑客的做法,但它完成了工作。


9
投票

我赞成@rebello95 的回应,因为这是一种方法。但另一种不那么老套的方法是这样做

- (void)whereIManuallyChangeTextView
{//you don't actually have to create this method. It's simply wherever you are setting the textview to empty
  [self.textView setText:@""];
  [self respondToChangeInTextView:self.textView];
}
    
- (void)textViewDidChange:(UITextView *)textView
{
  //...some work and then
  [self respondToChangeInTextView:textView];
}
    
- (void)respondToChangeInTextView:(UITextView *)textView
{
  //what you want to happen when you programmatically/manually or interactively change the textview
}

此代码片段体现了一种值得尊敬的模式,它将使您的代码更具可读性。


4
投票

在 swift 中,您可以覆盖

text
类中的
UITextView
变量:

class MyTextView: UITextView {

    override public var text: String? {
        didSet {
            self.textViewDidChange(self)
        }
    }

}

2
投票

旧帖子,但我遇到了同样的问题,并认为我会分享我的解决方案(在 Swift 中)。

仅设置文本属性不会调用

textViewDidChange(_ textView: UITextView)
,但使用
replace(range: UITextRange, withText: String)
时会调用它。因此,您需要为 UITextView 的整个字符串创建一个 UITextRange 并用新字符串替换它。

// Create a range of entire string
let textRange = textView.textRange(from: textView.beginningOfDocument, to: textView.endOfDocument)
// Create a new string
let newText = ""
// Call Replace the string in your textView with the new string
textView.replace(textRange!, withText: newText)

应该可以了。当然,您需要设置 UITextViewDelegate 才能使其工作:

class ViewController: UIViewController, UITextViewDelegate {

0
投票

您还可以子类化 UITextView 并重写 setText 以包含

[self textViewDidChange:self.textView]

这样您就不必每次设置 UITextView 的文本时都调用它。


0
投票

委托方法

textDidChange
不响应文本中的编程更改,您可以使用观察来获取通知

  1. 使用
    @objc dynamic
  2. 声明文本视图变量
  3. 声明并保存类型为
    NSKeyValueObservation
  4. 的变量
  5. 使用函数
    observe(_:changeHandler:)
    绑定文本视图的文本属性,用步骤2中声明的变量保存返回值
  6. 观察changeHandler中的变化

示例:

@objc dynamic private var textView: UITextView!
private var observation: NSKeyValueObservation?

func bind() {
    observation = observe(\.textView.text, options: [.old, .new]) { object, change in
        print(object, change)
    }
}

0
投票

Swift 5 解决方案... 如果您在这里希望在用户在 UITextView 中输入时实现运行字数统计,就像我一样,您可以使用以下内容:

首先,将 UITextViewDelegate 添加到类名中:

class YourClassName: UIViewController, UITextViewDelegate {

然后在你的 viewDidLoad() 中将委托设置为 self:

tvMyTextView.delegate = self

最后添加TextViewDidChange的委托方法:

func textViewDidChange(_ textView: UITextView) {
    let str = tvMyTextView.text
    let components = str!.components(separatedBy: .whitespacesAndNewlines)
    let words = components.filter { !$0.isEmpty }
    lblWordCount.text = "Word Count So Far: \(words.count)"
}

在我的委托方法中,我计算的是实际单词数,而不是字符数。当用户键入时,字数统计会不断更新并显示在我添加到名为“lblWordCount”的视图中的标签中。希望这对那里的人有帮助!


-1
投票

使用这个代替:(这不会重置当前文本

[self.textView insertText:@"something"];

这将调用委托并在光标所在位置添加文本。当然,如果您想重置整个文本,您可以:

[self.textView setText:@""];
[self textViewDidChange:self.textView];

[self.textView setText:@""];
[self.textView insertText:@"something"];
© www.soinside.com 2019 - 2024. All rights reserved.