Могу ли я обнаружить ключ удаления, даже если UITextField пуст?
Когда UITextField ничего не содержит, нажатие клавиши удаления клавиатуры не вызовет никаких методов UITextFieldDelegate.
Как я могу его обнаружить?
EDIT:
Кажется, нет тривиального способа сделать это. Наиболее полезные ссылки, которые я могу найти, следующие:
Короче говоря, мое решение состоит в том, чтобы поместить постоянное пространство в начало текстового поля. И сделайте другие ненужные изменения (textFieldShouldReturn:, textField: shouldChangeCharactersInRange: replacementString:, и т.д.).
Ответы
Ответ 1
Его можно навести на него кнопку, но это немного хрупко, поскольку раскладка клавиатуры может измениться с разными версиями iOS, и, разумеется, существуют разные раскладки клавиатуры для разных языков.
Посмотрите на "Управление текстовыми полями и текстовыми представлениями" в документе Apple. Я уверен, что есть способ сделать это. Его что-то вроде UITextField реализует протокол для получения ключей. Одним из этих ключевых событий, вероятно, будет клавиша удаления, поэтому вы можете переопределить любой метод, получающий их, и получить его таким образом.
Ответ 2
Это похоже на подклассу UITextField. UITextField соответствует протоколу UITextInput, который inturn соответствует другому протоколу UIKeyInput. Протокол UIKeyInput имеет метод deleteBackward, который срабатывает при каждом нажатии клавиши backspace на клавиатуре.
Вот как выглядит
Заголовок
#import <UIKit/UIKit.h>
@interface EmptyDeleteTextField : UITextField
@end
Реализация
- (void)deleteBackward
{
NSLog_SM(@"Length: %d", (int)self.text.length);
[super deleteBackward];
}
PS: Не забудьте вызвать супер, потому что вы не хотите вмешиваться в поведение UITextField по умолчанию.
Ответ 3
Я добавляю этот ответ для более полного примера в swift 3. По сути, мне нужно представление типа пин-кода, где у меня есть несколько текстовых полей, которые позволяют один символ в каждой ячейке.
вот так
Я начал с создания подкласса UITextField и протокола, который определяет новую функцию.
protocol MYDeleteActionTextFieldDelegate {
func textFieldDidSelectDeleteButton(_ textField: UITextField) -> Void
}
class MYDeleteActionTextField: UITextField {
var deleteDelegate: MYDeleteActionTextFieldDelegate?
override func deleteBackward() {
// Need to call this before super or the textfield edit may already be in place
self.deleteDelegate?.textFieldDidSelectDeleteButton(self)
super.deleteBackward()
}
}
Затем вы создаете текстовые поля с новым подклассом и реализуете делегат в вашем контроллере представления. В моем случае я управляю текстовыми полями в массиве для простоты использования и разметки ячеек с помощью PureLayout. Я храню их так
var pinFields = UITextField
Затем в viewDidLoad()
я добавляю все поля контактов в массив следующим образом:
for _ in 1...6 {
let field = EDFDeleteActionTextField.init(forAutoLayout: ())
field.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
field.delegate = self
field.deleteDelegate = self
field.textAlignment = .center
field.font = UIFont.newBigTitle()
field.textColor = UIColor.edfBlue()
field.backgroundColor = UIColor.edfWhite()
self.pinFields.append(field)
self.pinView.addSubview(field)
}
Теперь вам просто нужно ответить на все соответствующие методы делегата и цель textFieldDidChange
которая была добавлена выше.
// MARK: UITextFieldDelegate
func textFieldDidChange(textField: UITextField) {
// If the user typed one character, move to the next cell.
if (textField.text?.characters.count == 1) {
let index = pinFields.index(of: textField)
textField.resignFirstResponder()
if (pinFields.count > index! + 1) {
pinFields[index! + 1].becomeFirstResponder()
}
} // If they deleted the character move to previous cell
else if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.location > 0 {
let index = pinFields.index(of: textField)
// If there is already text in the text field and the next cell is empty - move the newly typed character to that cell.
if (pinFields.count > index! + 1) {
let nextField = pinFields[index! + 1]
if (nextField.text?.characters.count == 0) {
textField.resignFirstResponder()
nextField.becomeFirstResponder()
nextField.text = string
}
}
return false
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
// MARK: EDFDeleteActionTextFieldDelegate
func textFieldDidSelectDeleteButton(_ textField: UITextField) {
// If user clicked delete, and there are no characters, move to previous cell if available.
// If there are characters, it is handled in UITextFieldDelegate
if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
else {
textField.resignFirstResponder()
}
}
}
Я опущу скучные части (например, разметку текстовых полей и т.д.), Поскольку эта общая функциональность полезна в большем количестве случаев, чем представление с пин-кодом, но реализация этого дочернего класса и протокола должна дать все функциональные возможности, которые вам понадобятся для аналогичного типа рассматривает и решает вопрос под рукой (который, вероятно, нуждается в чем-то подобном).
Удачного кодирования.
Ответ 4
Хорошо, я понял это. поэтому в
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
делегата (т.е. когда текст будет введен для ввода), вы просто выполняете
if (text.length <= 0) {
// backspace
return FALSE;
} else {
потому что для backspace text.length будет == 0, а все остальное будет == 1.
Ответ 5
Это может быть реализовано путем подкласса UITextField и добавления его как пользовательского класса желаемого текстового поля.
Затем переопределите метод "deleteBackward"
Этот метод поймает все события backspace.
Код в Swift:
override func deleteBackward() {
super.deleteBackward()
// Enter your stuff here
}
Также убедитесь, что вы также вызываете супер метод, так как он выполняет основные функции события.
Ответ 6
Поместите над ним невидимую кнопку.
Ответ 7
Я не уверен, но вы можете попробовать собственный метод, используя addTarget: action: forControlEvents:
. Попробуйте параметр UIControlEventAllEditingEvents
.
Ответ 8
Для Q1.
У меня в Swift 4.2 ниже работает
@objc func keyboardInputShouldDelete(_ textField: UITextField) -> Bool {
print("User Pressed backspace in empty textfield ")
return true
}
Ответ 9
При использовании клавиатуры вы, очевидно, записываете ее в какую-либо переменную (например: UITextField, UILabel или даже глобальную строку)
Опцией для обнаружения действия удаления может быть:
- Хранить глобальный "int previousLengthOfText"
- Инициализировать этот var как
lastLengthOfText = 0;
- уловить изменение функции делегата: например:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
- сравните длину вашей метки \textField с этим глобальным var и посмотрите, был ли добавлен или удален символ.
например:
if ([self.myTextField.text length] > previousLengthOfText) {
{
// user deleted a character - Do your action here
previousLengthOfText = [self.myTextField.text length];
}