【问题标题】:What's the best way to get UITextField selection changed notifications?获取 UITextField 选择更改通知的最佳方法是什么?
【发布时间】:2011-12-20 17:24:28
【问题描述】:

使用通知中心,如How can I get a textDidChange (like for a UISearchBar) method for a UITextField? 中所述,允许您在 iOS UITextField 中的文本更改时收到通知。我没有看到类似的选择更改通知。检测和响应 UITextField 选择变化的最佳方法是什么?

【问题讨论】:

    标签: iphone ios ipad uitextfield


    【解决方案1】:

    这个link 有一个解决方案,不会弄乱私有 api:

    简而言之:子类UITextField,实现

    -(BOOL)canPerformAction:(SEL)action withSender:(id)sender
    

    并检查选择范围是否已更改。但这不会通知水龙头。

    所以我所做的是在子类化之后,观察selectedTextRange 属性:

    -(void)awakeFromNib {
        [self addObserver:self forKeyPath:@"selectedTextRange" options:0 context:nil];
    }
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        [self notifyDelegateIfNecessary];
    }
    

    在 iOS8 中运行良好。

    【讨论】:

    • 如果您确实继承了 UITextField,为什么不覆盖 [UITextField setSelectedTextRange:(UITextRange *)selectedTextRange]?然后所有的变化都发生在这个地方。
    • @Leo 1. 我不想改变行为,只收到通知 2. 我刚刚签入 PlayGround,我认为您无法覆盖该功能。
    • 它适用于我(IOS 8+9)。这样我就可以在合适的地方围绕移除观察者的需要。
    • 您的选择,我不会覆盖私有方法,但可能是一种品味。
    • @Krisdigital 如果您覆盖 setSelectedTextRange 并在其实现调用 [super setSelectedTextRange:text] 中,您将保持超类的原始行为还能得到一个通知点
    【解决方案2】:

    有一种简单的方法可以检测 textField 中的选择

    在 viewDidAppear 中添加对象属性观察器

      [self.keyboardInputFieldPassword addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld  context:nil];
    

    然后为属性添加观察功能

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if([keyPath isEqualToString:@"selectedTextRange"] && self.keyboardInputFieldPassword == object)
            [self textFieldDidChangeSelection:self.keyboardInputFieldPassword];
    }
    

    这将捕获 UITextField 中的选择范围

    为了遵守约定,你应该在 viewDidDisappear 中删除Observer

    [self.keyboardInputFieldPassword removeObserver:self forKeyPath:@"selectedTextRange" context:nil];
    

    【讨论】:

      【解决方案3】:

      斯威夫特 4

      private func listenForSelection(in textField:UITextField) {
          textField.addObserver(self, forKeyPath: "selectedTextRange", options: [.new,.old], context: nil)
      }
      private func unlistenForSelection(in textField:UITextField) {
          textField.removeObserver(self, forKeyPath: "selectedTextRange")
      }
      
      override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
          let textField = object as? UITextField
          assert(keyPath == "selectedTextRange")
          assert(textField != nil)
          // select everything but the first and last characters - just and example of the UITextInput API if you want to modify the selection
          if let startPosition = textField.position(from: textField.beginningOfDocument, offset: 1),
              let endPosition = textField.position(from: textField.endOfDocument, offset: -1) {
              let selectionRange = textField.textRange(from: startPosition, to: endPosition)
              textField.selectedTextRange = selectionRange
          }
      }
      

      【讨论】:

        【解决方案4】:

        将使用目标/操作的方法连接到UITextField 实例上的UIControlEventEditingChanged 控制事件。这可以在界面构建器或代码中通过将目标/操作对添加到文本字段然后实现指定的方法来完成。

        [self.textField addTarget:self action:@selector(textFieldTextChanged:) forControlEvents:UIControlEventEditingChanged];
        

        UITextField 还声明了一个UITextFieldDelegate 协议,其中包含您可以在类中实现的方法,以便在UITextField 实例的更改时收到通知。我建议您熟悉委托,因为它是 Cocoa 框架中的常见模式。

        UITextFieldDelegate Class Reference

        【讨论】:

        • UIControlEventEditingChanged 仅指文本编辑。即,仅当文本更改而文本字段 isEditing 时才会触发该操作。这不包括选择更改。
        猜你喜欢
        • 1970-01-01
        • 2010-09-20
        • 2020-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多