Отключить автозамену после ввода слов с префиксом @, затем снова включить при вводе нового слова

В моем text view я бы хотел, чтобы автозамена была отключена при вводе слов, начинающихся с "@". Причина в том, что у меня есть всплывающее меню tableview, предлагающее имена пользователей. Если выбрано имя пользователя, текущий текст заменяется на hyperlink. Эта функция очень похожа на Facebook.

Все отлично работает, если в моем текстовом представлении отключена автокоррекция. Однако, если я включу автозамену в текстовом представлении, временами он будет работать неправильно из-за предложенного текста. Вот мой код, в котором я пытаюсь изменить свойство автозамены текстового представления в протоколе делегата:

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

    if ([text isEqualToString:@"@"]) { 

        // text starts with "@" so we disable autocorrect

        textView.autocorrectionType = UITextAutocorrectionTypeNo;

    } else if ([text isEqualToString:@" "]) { 

        // empty space so we reenable autocorrect

        textView.autocorrectionType = UITextAutocorrectionTypeYes;
    }

    return YES;
}

По какой-то причине он не работает, хотя свойство автозамены изменяется правильно. Я проверил свойство автозамены textview в отладчике, и оно определенно меняется, а вот поведение во время набора текста - нет. Автокоррекция никогда не отключается, когда это необходимо, потому что меню автокоррекции по-прежнему отображается под текущим текстом:

введите описание изображения здесь

Изменить: все заработало. Лучшим решением, по-видимому, является изменение вашего респондента на другое скрытое текстовое представление, установка свойства autocorrectType исходных текстовых представлений, а затем переназначение исходного текстового представления в качестве первого респондента. Это немного взломано, но работает и не заставляет клавиатуру прыгать. Также важно проверить текущее свойство autocorrectionType textViews, чтобы предотвратить повторные назначения респондентов. Большое спасибо Линдси за помощь в поиске ответа.

  • (BOOL) textView: (UITextView *) textView shouldChangeTextInRange: (NSRange) range replaceText: (NSString *) text {if ([text isEqualToString: @ "@"] && textView.autocorrectionType! = UITextAutocorrectionTypeNo) {

    // text starts with "@" so we disable autocorrect
    [self.hiddenTextView becomeFirstResponder];
    textView.autocorrectionType = UITextAutocorrectionTypeNo;
    [textView becomeFirstResponder];
    

    } else if ([text isEqualToString: @ ""] && textView.autocorrectionType! = UITextAutocorrectionTypeYes) {

    // empty space so we reenable autocorrect
    [self.hiddenTextView becomeFirstResponder];
    textView.autocorrectionType = UITextAutocorrectionTypeYes;
    [textView becomeFirstResponder];
    

    }

    вернуть ДА; }


person Scott Kaiser    schedule 04.12.2014    source источник
comment
Вот предложение, которое может сработать: stackoverflow.com/a/8656965/2274694   -  person Lyndsey Scott    schedule 05.12.2014
comment
На самом деле, я думаю, что нашел лучший ответ ... Секунду.   -  person Lyndsey Scott    schedule 05.12.2014


Ответы (3)


Я нашел отличный ответ Энгина Курутепе о том, как правильно включить автозамену.

Решение очень простое, но не задокументировано: вы можете изменять только свойства, определенные в протоколе UITextInputTraits, в то время как рассматриваемый UITextView НЕ является первым респондентом.

Итак, в этом случае попробуйте:

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

    if ([text isEqualToString:@"@"]) { 

        // text starts with "@" so we disable autocorrect
        [textView resignFirstResponder];
        textView.autocorrectionType = UITextAutocorrectionTypeNo;
        [textView becomeFirstResponder];

    } else if ([text isEqualToString:@" "]) { 

        // empty space so we reenable autocorrect
        [textView resignFirstResponder];
        textView.autocorrectionType = UITextAutocorrectionTypeYes;
        [textView becomeFirstResponder];
    }

    return YES;
}

Редактировать:

И хотя решение, несомненно, является чем-то вроде "взлома", как вы указали в комментариях, аргументация, предоставленная Энгином, не соответствует действительности, и она вполне может быть законной, даже если она не задокументирована должным образом. Итак, если на самом деле верно, что «вы можете изменять только свойства, определенные в протоколе UITextInputTraits, в то время как UITextView, о котором идет речь, НЕ является первым респондентом», то, возможно, вам придется использовать «взлом», похожий на код Я отправил; в этом случае вы также можете отредактировать метод, который сдвигает панель инструментов на основе полученных уведомлений с клавиатуры, чтобы ваша панель инструментов не сдвигалась, если автозамена находится в середине переключения. Возможно, попробуйте использовать логическое значение, например "midToggle", и установить / отключить его перед resignFirstResponder и becomeFirstResponder в shouldChangeTextInRange, чтобы панель инструментов знала, что в такие моменты она должна оставаться неподвижной.

person Lyndsey Scott    schedule 04.12.2014
comment
Спасибо за ответ, Линдси. Однако это действительно работает, это скорее взлом, чем исправление. Причина в том, что это заставляет панель инструментов над клавиатурой (inputAccessoryView текстового представления) подпрыгивать при вызове resignFirstResponder и beginFirstResponder. Если бы мне не требовалось, чтобы панель инструментов оставалась неподвижной над клавиатурой, все было бы нормально. - person Scott Kaiser; 05.12.2014
comment
@DJSK Закодированное решение - это взлом, но приведенные им доводы неверны и могут быть законными, даже если они не задокументированы. Если на самом деле верно, что вы можете изменять только свойства, определенные в протоколе UITextInputTraits, в то время как рассматриваемый UITextView НЕ является первым респондентом, то, возможно, вам придется использовать код, аналогичный тому, который я опубликовал, но затем отредактируйте метод, который сдвигает панель инструментов, чтобы она не сдвигала панель инструментов, если автозамена находится в середине переключения. Возможно, вам придется использовать bool как midToggle и устанавливать / отключать его в shouldChangeTextInRange. - person Lyndsey Scott; 05.12.2014
comment
Спасибо, Линдси. У меня все заработало благодаря вашей помощи. Мой ответ размещен, если он вам нужен. - person Scott Kaiser; 05.12.2014

Все заработало. Лучшим решением, по-видимому, является изменение вашего респондента на другое скрытое текстовое представление, установка свойства autocorrectType исходных текстовых представлений, а затем переназначение исходного текстового представления в качестве первого респондента. Это немного взломано, но работает и не заставляет клавиатуру прыгать. Также важно проверить текущее свойство autocorrectionType textViews, чтобы предотвратить повторные назначения респондентов. Большое спасибо Линдси за помощь в поиске ответа.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 
replacementText:(NSString *)text 
{
    if ([text isEqualToString:@"@"] && 
        textView.autocorrectionType != UITextAutocorrectionTypeNo) { 

        // text starts with "@" so we disable autocorrect
        [self.hiddenTextView becomeFirstResponder];
        textView.autocorrectionType = UITextAutocorrectionTypeNo;
        [textView becomeFirstResponder];

    } else if ([text isEqualToString:@" "] && 
               textView.autocorrectionType != UITextAutocorrectionTypeYes) { 

        // empty space so we reenable autocorrect
        [self.hiddenTextView becomeFirstResponder];
        textView.autocorrectionType = UITextAutocorrectionTypeYes;
        [textView becomeFirstResponder];
    }

    return YES;
}
person Scott Kaiser    schedule 05.12.2014

Менее хитрый способ решить эту проблему - проверить, является ли строка, которую вы вводите, той строкой, которую вы выбрали. Вы можете установить переменную для хранения строки, выбранной в didSelectRowInIndexPath. Затем в методе делегата textView shouldChangeTextInRange проверьте, соответствует ли replaceText строке, выбранной вами в didSelectRowAtIndexPath. Если не совпадает, верните false.

person DHennessy13    schedule 29.04.2016