Ответ 1
Многие люди говорили, что это ошибка, но поскольку эта проблема все еще существует в GM, я начинаю думать, что это может быть изменение в логике. С учетом сказанного я написал этот бит кода для своего приложения и протестировал его на iOS 7-8.
Этот код немного перед красной линией частных API, однако у вас не должно возникнуть проблемы с его использованием. Мое приложение с этим кодом находится в магазине приложений.
Добавьте следующий подкласс к вашему подклассу UITextField
.
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
BOOL shouldDelete = YES;
if ([UITextField instancesRespondToSelector:_cmd]) {
BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd];
if (keyboardInputShouldDelete) {
shouldDelete = keyboardInputShouldDelete(self, _cmd, textField);
}
}
BOOL isIos8 = ([[[UIDevice currentDevice] systemVersion] intValue] == 8);
BOOL isLessThanIos8_3 = ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.3f);
if (![textField.text length] && isIos8 && isLessThanIos8_3) {
[self deleteBackward];
}
return shouldDelete;
}
Чтобы объяснить немного, вызывали супер-реализацию этого метода, чтобы избежать потери унаследованного кода. После вызова -deleteBackward
, если текст отсутствует, а версия iOS находится между 8-8.2.
РЕДАКТИРОВАТЬ: 1/28/15
Также может оказаться полезным подкласс метода -deleteBackward вашего подкласса UITextField. Это исправляет несколько условных ошибок. Один из них, если вы используете пользовательскую клавиатуру. Вот пример метода.
- (void)deleteBackward {
BOOL shouldDismiss = [self.text length] == 0;
[super deleteBackward];
if (shouldDismiss) {
if ([self.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
[self.delegate textField:self shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""];
}
}
}
РЕДАКТИРОВАТЬ: ответ переводится на Xamarin, поскольку исходный вопрос задал это для Xamarin.
[Preserve]
[Export("keyboardInputShouldDelete:")]
private bool KeyboardInputShouldDelete(UITextField textField)
{
var shouldDelete = true;
if(RespondsToSelector(new Selector("_cmd")))
{
//Call base class
shouldDelete = Messaging.bool_objc_msgSend_IntPtr(Handle, Selector.GetHandle("_cmd"), textField.Handle);
}
//ios8 "bug": always call DeleteBackward even if the field is empty
if(Utils.IsIos8)
{
DeleteBackward();
return false;
}
return shouldDelete;
}
Проверено на ios 7.1 и 8.1
РЕДАКТИРОВАТЬ: 4/14/15
В iOS 8.3 эта проблема исправлена. Код Objective-C обновлен, чтобы отразить изменения.
РЕДАКТИРОВАТЬ: 7/24/15
Как прокомментировал @nischalhada, существует состояние, в котором текстовые поля -textField:shouldChangeCharactersInRange:replacementString:
вызывается дважды. Проблема связана с iOS >= 8.3 при использовании пользовательской клавиатуры. Мое решение не идеально, но оно выполняет эту работу, и я не уверен, есть ли другой способ. Поскольку оба вызова этого метода выполняются в одном и том же цикле запуска, мы будем использовать bool, чтобы отслеживать, когда выполнить код и отправить async на reset bool.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
BOOL toReturn = NO;
if (!self.shouldTextFieldPreventChange) {
self.shouldTextFieldPreventChange = YES;
dispatch_async(dispatch_get_main_queue(), ^{
// iOS8.3 custom keyboards might call this method along with internal iOS
// code. Allowing changes on the next run loop helps avoid this issue.
self.shouldTextFieldPreventChange = NO;
});
// do work...
}
return toReturn;
}