在 iOS8 的 UITextField 中检测退格 [英] Detect backspace in UITextField in iOS8

查看:39
本文介绍了在 iOS8 的 UITextField 中检测退格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For detecting the Backspace, I've overridden DeleteBackward method (should work with 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"消息

When I press "Backspace" button nothing happens. I expect "DeleteBackward" message should appear

环境:iOS8、xamarin

Environment: iOS8, xamarin

0

objective-c 上的类似问题:检测 UITextField 中的退格

Similar question on objective-c: Detect backspace in UITextField

我已经做了额外的检查.DeleteBackward 是来自 UIKeyInput 协议,所以我检查了 insertText 方法,这个方法很有效.

I've done additional check. DeleteBackwardis method from UIKeyInput protocol, so I've check insertText method, this method works perfactly.

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

我已经在objective-c 上检查了deleteBackward,它也能完美运行.

I've checked deleteBackward on objective-c and it works perfectly too.

你知道如何在 iOS8 中检测 UITextField 中的退格键吗?

Do you have any ideas how to detect backspace in UITextField in iOS8?

你能解释一下为什么没有调用 DeleteBackward 方法吗?

Could you please clarify why the DeleteBackward method was not called?

1

我已经向 Xamarin 的 论坛.看起来像是 iOS8 + xamarin 中的错误,因为在 iOS 7.1 中完美运行.

I've submitted the same question to the Xamarin's forum. Looks like a bug in iOS8 + xamarin, because in iOS 7.1 works perfactly.

这是一个错误.这是详细信息

推荐答案

很多人一直说这是一个错误,但由于这个问题仍然存在于 GM 我开始认为这可能是一个改变在逻辑上.话虽如此,我为我的应用编写了这段代码,并在 iOS 7-8 上对其进行了测试.

A lot of people have been saying this is a bug, but being that this problem still exists in the GM I'm starting to think it might be a change in logic. With that said, I wrote this bit of code for my app and have tested it on iOS 7-8.

这段代码在私有 API 的红线之前,但是你使用它应该没有问题.我的带有此代码的应用在应用商店中.

This code is slightly before the red line of private API's, however you should have no problem using it. My app with this code is in the app store.

将以下方法添加到您的 UITextField 子类中.

Add the following method to your UITextField subclass.

- (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.

To explain a little, were calling the super's implementation of this method to avoid losing inherited code. After were going to call -deleteBackward if there is no text and the iOS version is between 8-8.2.

编辑:1/28/15

将子类化的 UITextField 的 -deleteBackward 方法子类化也可能会有所帮助.这修复了一些条件错误.一个是如果您使用自定义键盘.这是该方法的示例.

It also might be helpful to subclass the -deleteBackward method of your subclassed UITextField. This fixes a few conditional bugs. One being if you use a custom keyboard. Heres an example of the method.

- (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 提出的.

EDIT: answer translated to Xamarin, as the original question asked this for 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 上验证

Verified on ios 7.1 and 8.1

编辑:4/14/15

自 iOS 8.3 起,此问题已得到修复.已更新 Objective-C 代码以反映更改.

As of iOS 8.3 this issue has been fixed. The Objective-C code has been updated to reflect the changes.

编辑:7/24/15

正如@nischalhada 评论的那样,存在文本字段 -textField:shouldChangeCharactersInRange:replacementString: 被调用两次的状态.使用自定义键盘时,iOS >= 8.3 上存在此问题.我的解决方案并不理想,但它可以完成工作,我不确定是否还有其他方法.由于对这个方法的两次调用都是在同一个运行循环中执行的,我们将使用 bool 来跟踪何时执行代码,并使用 dispatch async 来重置 bool.

As @nischalhada commented, a state exists where the text fields -textField:shouldChangeCharactersInRange:replacementString: is called twice. The problem exists on iOS >= 8.3 while using a custom keyboard. My solution is not ideal but it does the job and I'm not sure if there's any other way. Since both calls to this method are performed on the same run loop we'll use a bool to keep track of when to execute the code and a dispatch async to reset the 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;
}

这篇关于在 iOS8 的 UITextField 中检测退格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆