UISearchBar завершает работу с исключением NSRangeException

#swift #uisearchbar

Вопрос:

Я столкнулся с этой ошибкой в своем приложении, и, по-видимому, она также появляется во многих других приложениях, особенно в приложениях Apple, таких как музыка, новости… Если вы используете функцию поиска в этих приложениях, введите что-нибудь в нее, а затем дважды щелкните строку поиска, чтобы открыть курсоры выделения текста. Удерживая первый курсор, перетащите его влево или вправо, не выходя за пределы последнего курсора. Продолжайте удерживать первый курсор и наберите что-нибудь на клавиатуре, приложение завершит работу с исключением NSRangeException. введите описание изображения здесь

Поскольку я использую UISearchBar в своем приложении, у меня та же проблема. Я не уверен, является ли это известной ошибкой или нет, но, похоже, я не могу найти никакой информации в Интернете. Есть ли обходной путь без изменения панели поиска на что-то другое? Также есть способ захватить событие touchesend (когда ваш палец покидает курсор после его перемещения), чтобы я мог продолжить изучение этой проблемы, я попробовал функцию touchesend UITextFieldDelegate, но она не работает.

Комментарии:

1. Разве вы не можете просто запретить выделение текста?

2. @GustavoConde Это окно поиска, оно должно работать как есть.

Ответ №1:

Я нашел обходной путь. Это не идеальное решение, так как оно не решает корень проблемы, но с точки зрения пользовательского опыта оно так же хорошо. Сначала вам нужно расширить UISearchTextFieldDelegate для вашего SearchViewController и переопределить методы textFieldDidChangeSelection и shouldChangeCharactersIn. Добавьте флаг, указывающий, активны ли двойные курсоры.

 func textFieldDidChangeSelection(_ textField: UITextField) {  if textField.selectedTextRange?.start != textField.selectedTextRange?.end {  flag = false  } else {  flag = true  } }  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -gt; Bool {  if !flag {  searchBar.resignFirstResponder()   // calculate the end position of the cursor  let tempRangeS = textField.offset(from: textField.beginningOfDocument, to: textField.selectedTextRange!.start)  let endPosition = textField.position(from: textField.beginningOfDocument, offset: tempRangeS   string.count)   // replace the selected text  if let textRange = textField.selectedTextRange {  textField.replace(textRange, withText: string)  }   searchBar.becomeFirstResponder()   // move the cursor to the end position  if endPosition != nil {  textField.selectedTextRange = textField.textRange(from: endPosition!, to: endPosition!)  }  return false  }  return true }  

Отказавшись от фокуса, вы эффективно удаляете выбор пользователя, который в первую очередь вызывает сбой, затем вычисляете, где должен находиться курсор после замены текста, и перемещаете курсор туда только после того, как снова установите фокус.