VENTokenField 按住退格键删除令牌

VENTokenField hold backspace key to delete tokens

在尝试允许删除多个令牌时,由于用户在 VENTokenField 中按住退格键以与本机电子邮件应用程序或消息应用程序相同,我遇到了很多问题...

首先,我只能从 VENToken 的 UITextField 子类提供的初始代码(技术上涉及私有 API)检测到一次点击退格键 - (BOOL)keyboardInputShouldDelete:(UITextField *)textField。这很好,但对于检测退格按钮上的长按没有帮助,退格按钮仅在您实际在某个 UITextField 中有字符时有效,而不是在 UITextField 为空时(例如在我们的例子中)。

我也遇到过这个 blogpost,它提出了另一种访问更多私有 API 的方法,但是,它没有提供解决我的问题的方法。由于没有记录,我想知道是否有一种有效的方法来检测此事件?

我首先解决了它,注释掉 VENBackspaceTextField class'

中的所有内容
keyboardInputShouldDelete:(UITextField *)textField 

然后,在 VENTokenField 中添加 2 个常量 header:

NSString * const kTextEmpty = @"\u200B"; // Zero-Width Space
NSString * const kTextHidden = @"\u200D"; // Zero-Width Joiner

每次令牌成为第一响应者时,确保文本字段为空文本:

- (void)inputTextFieldBecomeFirstResponder {    
   [self.inputTextField becomeFirstResponder];
   if (self.tokens.count) {
      [self.inputTextField setText:kTextEmpty];
   }
   ...
}

并在光标不可见时将其设置为隐藏:

- (void)setCursorVisibility {
   NSArray *highlightedTokens = [self.tokens filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(VENToken *evaluatedObject, NSDictionary *bindings) {
    return evaluatedObject.highlighted;
   }]];
   BOOL visible = [highlightedTokens count] == 0;
   if (visible) {
      [self inputTextFieldBecomeFirstResponder];
   } else {
      [self.invisibleTextField becomeFirstResponder];
      [self.invisibleTextField setText:kTextHidden];
   }
}

然后,修改textField Delegate方法:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (self.tokens.count && [string isEqualToString:@""] && [textField.text isEqualToString:kTextEmpty]){
    VENToken *lastToken = [self.tokens lastObject];
    lastToken.highlighted = YES;
    [_inputTextField setText:kTextHidden];
    _inputTextField.alpha = 0.0;
    return NO;
}

if ([textField.text isEqualToString:kTextHidden]){
    [self deleteHighlighted];
    [self unhighlightAllTokens];

    return (![string isEqualToString:@""]);
}

//If there are any highlighted tokens, delete
[self deleteHighlighted];
return YES;
}