锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / textDocumentProxy.documentContextBeforeInput.isEmpty突然异常返回Nil
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源,禁止转载和任何形式的非法内容使用,违者必究


textDocumentProxy.documentContextBeforeInput.isEmpty突然异常返回Nil

我正在制作一个自定义的iOS键盘 - 大部分工作已经到位,但我在删除键方面遇到了问题,更具体地说,删除了整个单词。

问题是self.textDocumentProxy.documentContextBeforeInput?.isEmpty返回Nil,即使text成员中还有字符。

这里是背景:iOS键盘的工作方式是,在按住退格键的同时,系统会一次删除一个字符(前10个字符)。10个字符后,它开始删除整个单词。

在我的代码中,我删除了10个单个字符,然后我成功删除了几个完整的单词,然后突然,self.textDocumentProxy.documentContextBeforeInput?.isEmpty返回Nil,即使text成员中还有字符。

我浏览过所有的文档和网页,我没有看到其他人有同样的问题,所以我肯定我错过了一些明显的东西,但我很困惑。

以下是我的类定义的相关部分:

class KeyboardViewController: UIInputViewController { 

//I've removed a bunch of variables that aren't relevant to this question.

    var myInputView : UIInputView {
    return inputView!
}
private var proxy: UITextDocumentProxy {
    return textDocumentProxy
}
override func canBecomeFirstResponder() -> Bool {
    return true
}

override func viewDidLoad() {
    super.viewDidLoad()
    //proxy let proxy = self.textDocumentProxy


    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillAppear"), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide"), name: UIKeyboardWillHideNotification, object: nil)


    self.myInputView.translatesAutoresizingMaskIntoConstraints = true

    // Perform custom UI setup here
    view.backgroundColor = UIColor(red: 209 / 255, green: 213 / 255, blue: 219 / 255, alpha: 1)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "touchUpInsideLetter:", name: "KeyboardKeyPressedNotification", object: nil)

    showQWERTYKeyboard()
}

我为backspace按钮设置了监听器和动作,因为我还在按钮上配置了一堆其他属性。我在Switch中这样做 - 比如:

            normalButton.setTitle(buttonString, forState: UIControlState.Normal)
            normalButton.addTarget(self, action: "turnBackspaceOff", forControlEvents: UIControlEvents.TouchUpInside)
            normalButton.addTarget(self, action: "turnBackspaceOff", forControlEvents: UIControlEvents.TouchUpOutside)
            normalButton.addTarget(self, action: "touchDownBackspace", forControlEvents: UIControlEvents.TouchDown)
            let handleBackspaceRecognizer : UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleBackspaceLongPress:")
            normalButton.addGestureRecognizer(handleBackspaceRecognizer)

以下是设计用于创建退格行为的4个功能。它们似乎至少在前两个单词中正常工作,但是以前正确的可选检查开始判断为Nil,并停止删除

func turnBackspaceOff() {

    self.backspaceIsPressed = false
    keyRepeatTimer.invalidate()

}

//Handles a single tap backspace
func touchDownBackspace() {

    (textDocumentProxy as UIKeyInput).deleteBackward()

}

//Handles a long press backspace
func handleBackspaceLongPress(selector : UILongPressGestureRecognizer) {

    if selector.state == UIGestureRecognizerState.Began {
        self.backspaceIsPressed = true
        self.keyRepeatTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "backspaceRepeatHandlerFinal", userInfo: nil, repeats: true)
        print("handleBackspaceLongPress.Began")
    }
    else if selector.state == UIGestureRecognizerState.Ended {
        self.backspaceIsPressed = false
        keyRepeatTimer.invalidate()
        numberOfKeyPresses = 0
        print("handleBackspaceLongPress.Ended")
    }
    else {
        self.backspaceIsPressed = false
        keyRepeatTimer.invalidate()
        numberOfKeyPresses = 0
        print("handleBackspaceLongPress. Else")
    }

}

func backspaceRepeatHandlerFinal() {

        if let documentContext = proxy.documentContextBeforeInput as String? {
            print(documentContext)
        }

        print("backspaceRepeatHandlerFinal is called")
        if self.backspaceIsPressed {
            print("backspace is pressed")
            self.numberOfKeyPresses = self.numberOfKeyPresses + 1

            if self.numberOfKeyPresses < 10 {

                    proxy.deleteBackward()

            }
            else {

                if let documentContext = proxy.documentContextBeforeInput as NSString? {
                        let tokens : [String] = documentContext.componentsSeparatedByString(" ")
                        var i : Int = Int()
                    for i = 0; i < String(tokens.last!).characters.count + 1; i++ {
                            (self.textDocumentProxy as UIKeyInput).deleteBackward()
                        }

                }
                else {
                    print("proxy.documentContextBeforeInput was nil")
                    self.keyRepeatTimer.invalidate()
                    self.numberOfKeyPresses = 0
                }
            }
        }
        else {
            print("In the outer else")
            self.keyRepeatTimer.invalidate()
            self.numberOfKeyPresses = 0
        }
}

最后,我不完全明白为什么,但是当我创建键盘扩展时,XCode在下面自动插入了这两个函数。为了努力实现这一目标,我稍微修改了它们。

override func textWillChange(textInput: UITextInput?) {
    // The app is about to change the document's contents. Perform any preparation here.
    super.textWillChange(textInput)
}

override func textDidChange(textInput: UITextInput?) {
    // The app has just changed the document's contents, the document context has been updated.

    var textColor: UIColor
    //let proxy = self.textDocumentProxy
    if proxy.keyboardAppearance == UIKeyboardAppearance.Dark {
        textColor = UIColor.whiteColor()
    } else {
        textColor = UIColor.blackColor()
    }
    super.textDidChange(textInput)
}

回答

让我们来描述下面这一行的内容:

if !((self.textDocumentProxy.documentContextBeforeInput?.isEmpty) == nil) {  

首先,它需要一个标记为optional(通过?字母)的对象:

let documentContext = self.textDocumentProxy.documentContextBeforeInput  

然后,它会尝试读取它的名为isEmpty:

let isEmpty = documentContext?.isEmpty  

然后评估这个关系:

if !(isEmpty == nil) {  

有两个错误。第一个是你正在比较Bool价值nil。另一个是你不确定那documentContext不是nil。

所以,让我们以更合适的方式编写代码:

if let documentContext = self.textDocumentProxy.documentContextBeforeInput { // Make sure that it isn't nil
    if documentContext.isEmpty == false { // I guess you need false?
        // Do what you want with non-empty document context
    }
}

总结

初学者对let的目标不清楚,对判断的目标不清楚才造成这样的问题。let对应可选成员,而==后面的内容要和ie前面的成员的类型一样。并且在逻辑关系复杂时,不要写综合性质的if语句,分开写更好理解。

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内