UITextView selectВсе метод не работает как ожидалось

Я создаю приложение iOS 8 с Xcode 6.0.1 для своего iPhone 5 (на нем есть iOS 8.0.2). Я хочу сделать так, чтобы, когда пользователь нажимает на мой UITextView, весь текст выбирается, поэтому он может легко начать вводить и стирать то, что было там (но я не хочу, чтобы текст автоматически стирался, потому что пользователь может хотите сохранить его или добавить к нему). Для этого у меня есть следующий код:

- (void)textViewDidBeginEditing:(UITextView *)textView {
    if ([textView hasText]) {
        NSLog(@"selectedRange before: %d", textView.selectedRange.length);
        [textView selectAll:self];
        NSLog(@"selectedRange after: %d", textView.selectedRange.length);
    }
}

Когда этот метод вызывается, вывод консоли - это то, что я ожидаю (т.е. длина selectedRange совпадает с количеством символов в тексте textView). Тем не менее, ничего не отображается, как выбрано в UITextView, и оно не действует (т.е. Всплывающее меню выбора).

Я видел несколько вопросов, подобных этому в Интернете, но ни один из предоставленных решений не работал у меня (и некоторые из них записывали его как ошибку, не предоставляя никакого решения). Изменение идентификатора отправителя на что-то, отличное от self (например, nil), не помогло, и также не помогло вызвать [textView select:self], как предложил один человек. Я также пробовал этот код:

- (void)textViewDidBeginEditing:(UITextView *)textView {
    if ([textView hasText]) {
        UITextRange *range = [textView textRangeFromPosition:textView.beginningOfDocument toPosition:textView.endOfDocument];
        [textView setSelectedTextRange:range];
    }
}

Но это имеет ту же проблему.

Любые предложения?

Ответ 1

Лучшим решением, которое я нашел для этой проблемы до сих пор, является создание пользовательского UITextView (т.е. создание нового класса, который расширяет UITextView), а затем реализовать метод selectAll следующим образом:

- (void)selectAll:(id)sender {
    [super selectAll:sender];
    UITextRange *selectionRange = [self textRangeFromPosition:self.beginningOfDocument toPosition:self.endOfDocument];
    [self performSelector:@selector(setSelectedTextRange:) withObject:selectionRange afterDelay:0.0];
}

Затем, когда вы используете текстовое представление, установите его тип в свой собственный тип текстового вида (в вашем коде и в раскадровке). Теперь вы можете успешно вызвать метод selectAll всякий раз, когда вам нужно. Я полагаю, что это тоже должно работать с UITextField, но я еще не пробовал.

Ответ 2

Это решение работает и не требует подкласса UITextView, просто поместите эту функцию в свой делегат:

ЦЕЛЬ C -

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
  dispatch_async(dispatch_get_main_queue(), ^{
    [textView selectAll:nil];
  });
  return YES;
}

SWIFT 3 -

func textViewDidBeginEditing(_ textView: UITextView) {
    DispatchQueue.main.async {
        textView.selectAll(nil)
    }
}

Ответ 3

Решение @brentvatne работало для меня. Публикация синтаксиса Swift, чтобы люди могли копировать и вставлять в будущем.

func textViewShouldBeginEditing(textView: UITextView) -> Bool {
    dispatch_async(dispatch_get_main_queue()) {
        textView.selectAll(nil)
    }
    return true
}