【问题标题】:Forcing lower case when shift key is pressed按下 shift 键时强制小写
【发布时间】:2017-10-15 14:56:22
【问题描述】:

我是一名初级 MacOS 开发人员。 在 Swift 4 Cocoa 中,我希望拥有对 Shift 键进行“特殊”处理的文本字段。

默认情况下,如果输入一个字母,它应该是大写的,但是如果按下 Shift 键,这个字母应该是小写的。

示例:

  • 输入“a” -> 转换为“A”
  • Shift+“a”输入->转换为“a”
  • 应正常处理任何其他条目(数字等)-

我可以用

强制转换为大写
override func controlTextDidChange(_ obj: Notification) {
    print("Text changed")

    var infoDictionary:Dictionary = obj.userInfo! as Dictionary
    let text:NSText = infoDictionary["NSFieldEditor"] as! NSText
    text.string = text.string.uppercased()
}

但是我不知道如何在按下 shift 键时“强制”为小写。

非常感谢您的阅读和...帮助。

【问题讨论】:

    标签: swift macos cocoa


    【解决方案1】:

    文本字段中的击键由The Field Editor 处理。字段编辑器是NSTextViewNSTextView 实现NSTextInputClient 协议。创建NSTextView 的子类并覆盖insertText(_:replacementRange:) 以更改输入字符串的大小写。

    class MyTextView: NSTextView {
    
        override func insertText(_ string: Any, replacementRange: NSRange) {
            var newString = string
    
            if let oldString = string as? String {
                if (NSApp.currentEvent?.modifierFlags.contains(.shift))! {
                    newString = oldString.lowercased()
                }
                else {
                    newString = oldString.uppercased()
                }
            }
            // handle string is a NSAttributedString
    
            super.insertText(newString, replacementRange:replacementRange)
        }
    
    }
    

    子类NSTextFieldCell 并覆盖fieldEditor(for:) 以返回NSTextView 子类的实例。

    class MyTextFieldCell: NSTextFieldCell {
    
        var myFieldEditor:MyTextView? = nil
    
        override func fieldEditor(for controlView: NSView) -> NSTextView? {
            if (myFieldEditor == nil) {
                myFieldEditor = MyTextView()
                myFieldEditor?.isFieldEditor = true
            }
            return myFieldEditor  
        }
    
    }
    

    将文本字段的单元格的类设置为MyTextFieldCell

    【讨论】:

      【解决方案2】:

      在输入阶段解决任务,而不是在文本输入字段之后。即在将传入的按键事件插入到文本字段之前转换其大小写。

      Apple 使用 字段编辑器 设置,该设置在编辑时有效地将任何 NSTextField 替换为 NSTextView。该过程在Working with the Field Editor 中进行了说明,概述为:

      • 您定义了NSTextView 的子类,它覆盖keyDown:,在调用被覆盖的方法([super ...])之前根据需要修改字符的大小写。您的覆盖将传递收到的 NSEvent 未修改或使用您的案例修改构建一个新的。

      • 包含您的文本字段的窗口 负责设置字段编辑器。在您的窗口委托中,您实现委托方法windowWillReturnFieldEditor:toObject:。如果此方法的第二个参数是您希望对其进行特殊处理的文本字段,则返回 NSTextView 子类的实例,并将其 fieldEditor 属性设置为 YES。否则你返回nil

      • 识别需要特殊处理的文本字段的一种简单方法是声明 NSTextField 的空子类并将其用于特殊文本字段。您的窗口委托方法现在可以进行类型测试了。

      如果您在制定解决方案时遇到问题,请提出一个新问题,显示您开发的代码、解释您的问题等,毫无疑问有人会帮助您进行下一步。

      HTH

      【讨论】:

      • 子类化NSTextField 不起作用,字段编辑器处理关键事件。覆盖 keyDown(with:) 不适用于 ü 和 é。
      • @Willeke - Egg-on-face,感谢您发现这一点。修复了覆盖正确keyDown:的答案。
      • @Willeke - 这就是我说“有效”的原因 ;-) Apple 自己写了“这种​​机制可能令人困惑”,我认为描述真正发生的事情只会混淆问题。
      • 说“替换”和“NSTextField/NSTextView”是令人困惑的。 NSControl 的子类使用字段编辑器,NSTextView 不使用。控件没有被替换,它仍然存在并且正在运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多