如何以编程方式关闭 UITextView 中的自动更正弹出框?

Posted

技术标签:

【中文标题】如何以编程方式关闭 UITextView 中的自动更正弹出框?【英文标题】:How can I programmatically dismiss the autocorrect popover in a UITextView? 【发布时间】:2012-08-31 14:50:02 【问题描述】:

我正在使用 insertText: 自己做一些自定义的自动完成工作,但如果有一个可见的自动更正建议,视图就会进入一个奇怪的状态。

如果我使用[textView unmarkText],它会关闭自动更正弹出窗口——但它会接受自动更正(这很糟糕)。有没有办法以编程方式拒绝自动更正建议?

我目前的“解决方案”有效,但它很粗俗,而且我没有理由认为它会在未来继续有效。有没有更好的方法来做到这一点?

- (void)dismissAutocorrectSuggestionForTextView:(UITextView *)textView 
    NSRange range = textView.selectedRange;
    textView.text = textView.text;
    textView.selectedRange = range;

【问题讨论】:

有什么原因不能将textView.autocorrectionType 设置为UITextAutocorrectionTypeNo 是的。该字段应具有自动更正功能。 【参考方案1】:

我尝试了与您类似的方法,但是以这种方式设置 textView 的文本会导致 textView 不必要地滚动(我的 textView 包含相当多的文本)。我的解决方案涉及以非动画方式恢复 contentOffset。它并不比你所拥有的更优雅,但至少它可以帮助那些需要处理更长文本的人。

至于以后是否会继续工作,我从ios 4开始就尝试过类似的方法,并且在iOS 6中继续工作。

- (void)rejectAutoCorrectSuggestionInTextView:(UITextView *)textView

    if ([textView isFirstResponder])
    
        NSString *original = textView.text;
        NSRange originalRange = textView.selectedRange;
        CGPoint originalOffset = textView.contentOffset;

        // Force any pending autocorrection to be applied
        [textView resignFirstResponder];
        [textView becomeFirstResponder];

        NSString *final = textView.text;

        if (![original isEqualToString:final])
        
            textView.text = original;
            textView.selectedRange = originalRange;
            [textView setContentOffset:originalOffset animated:NO];
        
    

【讨论】:

【参考方案2】:

我自己也遇到了这个问题。此解决方案效果很好:

[textView.inputDelegate textWillChange:textView];
[textView.inputDelegate textDidChange:textView];

【讨论】:

【参考方案3】:

您原来的解决方案很接近。请尝试以下操作:

- (void)dismissAutocorrectSuggestionForTextView:(UITextView *)textView 
    NSRange rangeCopy = textView.selectedRange;
    NSString *textCopy = textView.text.copy;
    [textView resignFirstResponder];
    [textView becomeFirstResponder];
    [textView setText:textCopy];
    [textView setSelectedRange:rangeCopy];

连续调用 resign/become first responder 会导致文本视图立即接受待处理的自动更正,但不会真正关闭键盘(尝试一下,您会感到惊讶)。这肯定适用于 iOS 6 和 iOS 7。接受自动更正后,您将文本和选定范围重置为自动更正之前的状态。

【讨论】:

这太棒了!谢谢。完美解决问题【参考方案4】:

如果不需要从文本视图中退出第一响应者,并且您可以作为委托附加到文本视图,则可以实现方法

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

return NO 在特定情况下。例如,您可以尝试以下操作:

@implementation

    BOOL _denyReplacements;


//////////////

- (void)dismissAutocorrectSuggestionForTextView:(UITextView *)textView 
    NSRange rangeCopy = textView.selectedRange;
    NSRange fakeRange = rangeCopy;
    fakeRange.location--;
    _denyReplacements = YES;
    [textView unmarkText];
    [textView setSelectedRange:fakeRange];
    [textView setSelectedRange:rangeCopy];
    _denyReplacements = NO;


- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 
     return !_denyReplacements;

当文本视图选择更改时,自动完成会尝试接受当前建议,但文本视图会在进行替换之前咨询此方法。例如,当您在 textViewDidBeginEditing 和/或 textViewDidEndEditing 方法中有一些逻辑时,您为什么要这样做而不是仅仅辞职/成为第一响应者的一个例子是,当您解雇自动更正。

【讨论】:

以上是关于如何以编程方式关闭 UITextView 中的自动更正弹出框?的主要内容,如果未能解决你的问题,请参考以下文章

你能以编程方式接受 UITextView 中的拼写更正吗?

我将如何(以编程方式)将 UITextView 的高度设置为其在 Swift 中的内容大小?

在 UITextView 上以编程方式禁用 iOS8 Quicktype 键盘

Swift - 以编程方式居中 UITextView

以编程方式将段落标题添加到 UITextView

UITextView 以编程方式调整大小,但随后设置为旧的故事板值。