Как я могу программно отклонить всплывающее окно автозамены в UITextView?
Я делаю некоторые собственные автозаполнения самостоятельно с insertText:
, но если есть видимое предложение автозамены, представление переходит в странное состояние.
Если я использую [textView unmarkText]
, он отклоняет всплывающее окно автозамены - но он принимает автокоррекцию (что плохо). Есть ли какой-нибудь способ программно отклонить предложение автозамены?
Мое текущее "решение" работает, но оно грубое и хакерское, и у меня нет оснований предполагать, что оно продолжит работать в будущем. Есть лучший способ сделать это?
- (void)dismissAutocorrectSuggestionForTextView:(UITextView *)textView {
NSRange range = textView.selectedRange;
textView.text = textView.text;
textView.selectedRange = range;
}
4 ответа
Я пробовал что-то похожее на ваше, но установка текста 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];
}
}
}
Я только что столкнулся с этой проблемой сам. Это решение хорошо работает:
[textView.inputDelegate textWillChange:textView];
[textView.inputDelegate textDidChange:textView];
Ваше оригинальное решение близко. Попробуйте следующее:
- (void)dismissAutocorrectSuggestionForTextView:(UITextView *)textView {
NSRange rangeCopy = textView.selectedRange;
NSString *textCopy = textView.text.copy;
[textView resignFirstResponder];
[textView becomeFirstResponder];
[textView setText:textCopy];
[textView setSelectedRange:rangeCopy];
}
При повторном вызове в отставку / становлении первым респондентом текстовое представление немедленно принимает ожидающие автокоррекции, но без фактического закрытия клавиатуры (попробуйте, вы будете удивлены). Это работает на iOS 6 и iOS 7 точно. Приняв автокоррекции, вы сбрасываете текст и выбранный диапазон до того, что было до автокоррекции.
Если отставка первого респондента из текстового представления нежелательна, и вы можете присоединиться как делегат к текстовому представлению, вы можете реализовать метод
- (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
методы, например, которые вы не хотите выполнять при отклонении автокоррекции.