精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品开源,禁止转载和任何形式的非法内容使用,违者必究
我正在制作一个自定义的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语句,分开写更好理解。