很多人一直说这是一个错误,但由于这个问题仍然存在于通用汽车中,我开始认为这可能是逻辑上的变化。话虽如此,我为我的应用程序编写了这段代码,并在 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之间。
EDIT: 2015 年 1 月 28 日
对子类 UITextField 的 -deleteBackward 方法进行子类化也可能会有所帮助。这修复了一些条件错误。其中之一是如果您使用自定义键盘。这是该方法的一个示例。
- (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:@""];
}
}
}
EDIT:答案翻译为 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 上验证
EDIT: 2015 年 4 月 14 日
自 iOS 8.3 起,此问题已得到修复。 Objective-C 代码已更新以反映这些更改。
EDIT: 2015 年 7 月 24 日
正如 @nischalhada 评论的那样,存在一种状态,其中文本字段-textField:shouldChangeCharactersInRange:replacementString:
被调用两次。使用自定义键盘时,iOS >= 8.3 上存在此问题。我的解决方案并不理想,但它可以完成工作,我不确定是否还有其他方法。由于对此方法的两次调用都是在同一个运行循环上执行的,因此我们将使用 bool 来跟踪何时执行代码,并使用调度异步来重置 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;
}