2017-01-23 43 views
1

我有一个NSTextView子类(Obj-C),它通过标准机制实现完成(实现completionsForPartialWordRange:indexOfSelectedItem:rangeForUserCompletion等)。过去,AppKit使用两种用户操作之一自动调用完成:按下command-。 (命令周期),或按esc(转义)。我刚刚切换到一个新的“2016年后期”的MacBook Pro,同时从10.11升级到10.12。代码完成不再适用于我的应用程序。我只是从响应者链中的深度呼叫NSBeep(),当时没有人回应那些按键。 NSTextViewcomplete:方法从未被击中(称调试器)。NSTextView绑定完成:在macOS 10.12上损坏?

我怀疑这是因为Apple做出的改变。我注意到complete:(在https://developer.apple.com/reference/appkit/nstextview/1449359-complete?language=objc)的文档已经改变;它曾经说complete:是由esc触发的,但现在它说它是由F5触发的(这在我的机器上似乎也不起作用,但功能键映射总是奇怪而难以理解,所以谁知道这一点)。

我通过重写doCommandForSelector:来做一个小小的调查,只是打印AppKit正在尝试的选择器,然后调用超级。事实证明,现在按esc现在导致doCommandForSelector:被调用cancelOperation:cancel:,并按下命令。现在导致cancel:。这是有道理的,因为这些键用于取消面板等,但这里没有涉及面板,没有取消操作等。

我的问题是:什么是最好的方式我简单地回到过去的行为?换句话说,在10.12和更高版本中,我仍然想要esc和command-。在我的应用中调用complete:。我发现苹果的文档通过plist文件更改了键绑定,但似乎并不是这样做的正确方法。也许我应该做一个覆盖,但我认为那些因关键事件的合并,国际键盘上的键码解释等的复杂而受到阻碍。我的理解是,干预事件处理通常太低。相反,我认为我应该以某种方式修改interpretKeyEvents:的行为,将我想要的密钥绑定到complete:,但我无法弄清楚如何在代码中执行此操作。

+0

关于'keyDown:'不是正确的做法,请注意例如苹果的文档(https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/EventOverview/HandlingKeyEvents/HandlingKeyEvents.html)它说:“它可以使用NSEvent的字符方法提取事件对象的字符并解释它们是否与已知的键盘动作相关联,如果是,它会自行调用适当的动作方法或超级视图,这种做法是不鼓励的。 – bhaller

+0

我想象他们改变了功能键映射,因为替换了功能键的触摸条。你见过这个文件吗(https://developer.apple。COM /库/内容/文档/ TextFonts /概念/ CocoaTextArchitecture/TextEditing/TextEditing.html)? “截取关键事件”部分讨论了如何使用委托捕获输入并使用textView:doCommandBySelector:为文本视图执行内容。 – malicedShade

+0

是的,我知道那个文件。它似乎没有解释的是应用程序如何更改键绑定。也就是说,我该如何做到这一点,以便在我的应用程序中逃脱转化为对'complete:'的调用,而不是像以前那样调用'cancel:'?这里提到用户如何在〜/ Library文件夹中使用plist来定义自定义的键绑定,但我没有看到任何有关在代码中更改特定应用程序中绑定的信息。这似乎是一个奇怪的疏忽。 – bhaller

回答

0

下面是覆盖keyDown:以使键绑定有效的答案。正如问题中提到的那样,我不确定这是否是正确/推荐的做事方式。

- (void)keyDown:(NSEvent *)event 
{ 
    NSString *chars = [event charactersIgnoringModifiers]; 
    NSEventModifierFlags flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; 

    if ([chars length] == 1) 
    { 
     unichar keyChar = [chars characterAtIndex:0]; 

     if ((keyChar == 0x1B) && (flags == 0)) 
     { 
      // escape key pressed 
      [self doCommandBySelector:@selector(complete:)]; 
      return; 
     } 
     if ((keyChar == '.') && (flags == NSEventModifierFlagCommand)) 
     { 
      // command-. pressed 
      [self doCommandBySelector:@selector(complete:)]; 
      return; 
     } 
    } 

    [super keyDown:event]; 
} 

如果有人给出更好的答案,我会很乐意选择它。

0

在Sierra中,“opt-esc”组合键取代了'esc'作为complete:的标准绑定。正如您所观察到的,未修改的'esc'现在绑定到cancelOperation:。对于我的应用程序,我记录了新的行为,而不是过度描述它,因为我怀疑苹果有这样一个恼人的变化的原因。