在iOS8中检测UITextField中的退格

时间:2014-08-17 23:07:23

标签: xamarin.ios xamarin ios8

为了检测Backspace,我覆盖了DeleteBackward方法(应该适用于iOS5 +)

var input = new BackspaceTextField(RectangleF.Empty);
etc
input.BecomeFirstResponder();

这是代码

public sealed class BackspaceTextField : UITextField
{
    public BackspaceTextField(RectangleF frame) : base(frame)
    {
    }

    public override void DeleteBackward ()
    {
        Console.WriteLine ("DeleteBackward");
    }
}

当我按“Backspace”按钮时没有任何反应。我希望应该出现“DeleteBackward”消息

环境:iOS8,xamarin

编辑:0

关于objective-c的类似问题:Detect backspace in UITextField

我已经做了额外的检查。 DeleteBackward是来自UIKeyInput协议的方法,因此我检查insertText方法,此方法可以正常工作。

public override void InsertText (string text)
{
   base.InsertText(text);
}

我在objective-c上检查了deleteBackward,它也完美无缺。

您是否有任何想法如何在iOS8中的UITextField中检测退格?

请您澄清为什么没有调用DeleteBackward方法?

修改:1

我已经向Xamarin的forum提交了同样的问题。看起来像iOS8 + xamarin中的一个错误,因为在iOS 7.1中可以正常工作。

这是一个错误。这是details

2 个答案:

答案 0 :(得分:24)

许多人一直在说这是一个错误,但由于这个问题在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;
}

要解释一下,请调用此方法的超级实现,以避免丢失继承的代码。如果没有文本且iOS版本介于8-8.2之间,则打电话给-deleteBackward

编辑: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:@""];
        }
    }
}

编辑:答案翻译成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代码已更新以反映更改。

编辑:2015年7月24日

正如@nischalhada所评论的那样,存在两次调用文本字段-textField:shouldChangeCharactersInRange:replacementString:的状态。使用自定义键盘时,iOS&gt; = 8.3存在问题。我的解决方案并不理想,但它完成了工作,我不确定是否还有其他办法。由于对此方法的两次调用都是在同一个运行循环上执行的,因此我们将使用bool来跟踪何时执行代码以及调度async以重置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;
}

答案 1 :(得分:1)

准确地说,这是一个Apple iOS8错误。在Apple的开发者论坛上,已经有几次reported次。遗憾的是,这些错误报告无法公开访问,因此我们所知道的是它仍然会发生在测试版5中。

附注:一般情况下(99%),大多数Xamarin.iOS绑定并非特定于iOS版本(即没有版本检查),因此iOS版本之间的不同行为通常是设计(记录在案)或 Apple bug (就像这个)。