启用NSArrayController“自动重新排列内容”时,插入和编辑新对象后,键盘焦点丢失 [英] Keyboard focus lost after inserting and editing new object, when NSArrayController „Auto Rearrange Content“ is enabled

查看:493
本文介绍了启用NSArrayController“自动重新排列内容”时,插入和编辑新对象后,键盘焦点丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主 - 详细类型的应用程序OS X 10.9:

窗口左侧的NSTableView,右侧的NSTextFields的详细信息。

我没有特别设置标签顺序,开箱即用工程很好。



插入新对象后,除了插入新对象之外:




    <
  • 选择第一个NSTextField

  • 写入某个内容,
  • 选择
  • 现在点击标签


  • 选择了第一个NSTextField

  • 选择了NSTableView

  • < b $ b


我想要什么:




  • 应选择细节部分的第一个NSTextField

  • 点击标签

  • 应选择细节部分的下一个NSTextField

  • ...



UPDATE:
我发现奇怪的行为是通过启用NSArrayController的 在Interface Builder中,如果我禁用它,我不会失去我的焦点了。见 CoreData-bound NSTableView在项目改变时丢失输入焦点,但只有在排序时才输入焦点。



当然,我仍然希望我的内容被自动排序 - 只是不会失去我的焦点在该操作。可以这样做吗?



UPDATE2:我跟着@KenThomases建议,并记录了当我的textfield失去键盘焦点时的堆栈跟踪:

  2014-08-17 16:30:26.003 ResponderExperiment [712:303](
0 ResponderExperiment 0x00000001000014dd - [WMWindow makeFirstResponder:] + 61
1 AppKit 0x00007fff8d25c778 - [NSTextView(NSPrivate)_giveUpFirstResponder:] + 257
2 AppKit 0x00007fff8d25c56c - [NSTextView(NSKeyBindingCommands)insertTab:] + 270
3 AppKit 0x00007fff8d22dc2f - [NSResponder doCommandBySelector:] + 71
4 AppKit的0x00007fff8d25b10a - [NSTextView doCommandBySelector:] + 196
5 AppKit的0x00007fff8d22d151 - [NSKeyBindingManager(NSKeyBindingManager_MultiClients)interpretEventAsCommand:forClient:] + 1392
6 AppKit的0x00007fff8d24c1c2 - [NSTextInputContext的handleEvent:] + 845
7 AppKit 0x00007fff8d22b9dd - [NSView interpretKeyEvents:] + 180
8 AppKit 0x00007fff8d24bd6d - [NSTextView keyDown:] + 658
9 AppKit 0x00007fff8d1f856b - [NSWindow sendEvent:] + 1843
10 AppKit 0x00007fff8d199b32 - [NSApplication sendEvent:] + 3395
11 AppKit 0x00007fff8cfe99f9 - [NSApplication run] + 646
12 AppKit 0x00007fff8cfd4783 NSApplicationMain + 940
13 ResponderExperiment 0x0000000100002de2 main + 34
14 libdyld .dylib 0x00007fff8c5bf5fd start + 1
15? 0x0000000000000003 0x0 + 3

2014-08-17 16:30:26.014 ResponderExperiment [712:303](
0 ResponderExperiment 0x00000001000014dd - [WMWindow makeFirstResponder:] + 61
1 AppKit 0x00007fff8d03c918 - [NSControl abortEditing] + 83
2 AppKit 0x00007fff8d2723e0 - [NSValueBinder discardEditing] + 162
3 AppKit 0x00007fff8d1aee30 - [NSController discardEditing] + 115
4 AppKit 0x00007fff8d1af971 - [NSArrayController rearrangeObjects] + 27
5 AppKit 0x00007fff8d3697a9 - [NSArrayController observeValueForKeyPath:ofObject:change:context:] + 294
6 AppKit 0x00007fff8d39ac08 - [NSArrayController _setMultipleValue:forKeyPath:atIndex:] + 323
7 AppKit 0x00007fff8d39ba12 - [ NSArrayController的_setSingleValue:forKeyPath:] + 137
8基金会0x00007fff8bf9e19a - [NSObject的(即NSKeyValueCoding)的setValue:forKeyPath:] + 285
9 AppKit的0x00007fff8d25444c - [NSBinder _setValue:forKeyPath:ofObject:模式:validateImmediately:raisesForNotApplicableKeys:错误:] + 364
10 AppKit 0x00007fff8d254287 - [NSBinder setValue:forBinding:error:] + 245
11 AppKit 0x00007fff8d74c4ee - [NSValueBinder _applyObjectValue:forBinding:canRecoverFromErrors:handleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo: didRunAlert:] + 194
12 AppKit的0x00007fff8d74c871 - [NSValueBinder applyDisplayedValueHandleErrors:typeOfAlert:canRecoverFromErrors:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:错误:] + 621
13 AppKit的0x00007fff8d74c9d4 - [NSValueBinder _applyDisplayedValueIfHasUncommittedChangesWithHandleErrors:typeOfAlert:discardEditingCallback: otherCallback:callbackContextInfo:didRunAlert:错误:] + 127
14 AppKit的0x00007fff8d253c2e - [NSValueBinder validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:] + 436
15 AppKit的0x00007fff8d253a57 - [_ NSBindingAdaptor _validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:bindingAdaptor:] + 160
16 AppKit的0x00007fff8d25399d - [_ NSBindingAdaptor validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:] + 260
17 AppKit的0x00007fff8d25e0ba - [的NSTextField textShouldEndEditing:] + 402
18 AppKit的0x00007fff8d25dc63 - [NSTextView(NSSharing)resignFirstResponder] + 393
19 AppKit 0x00007fff8d136170 - [NSWindow makeFirstResponder:] + 455
20 ResponderExperiment 0x000000010000154c - [WMWindow makeFirstResponder:] + 172
21 AppKit 0x00007fff8d25c778 - [NSTextView(NSPrivate)_giveUpFirstResponder:] + 257
22 AppKit 0x00007fff8d25c56c - [NSTextView(NSKeyBindingCommands)insertTab:] + 270
23 AppKit 0x00007fff8d22dc2f - [NSResponder doCommandBySelector:] + 71
24 AppKit 0x00007fff8d25b10a - [NSTextView doCommandBySelector:] + 196
25 AppKit的0x00007fff8d22d151 - [NSKeyBindingManager(NSKeyBindingManager_MultiClients)interpretEventAsCommand:forClient:] + 1392
26 AppKit的0x00007fff8d24c1c2 - [NSTextInputContext的handleEvent:] + 845
27 AppKit的0x00007fff8d22b9dd - [的NSView interpretKeyEvents:] + 180
28 AppKit 0x00007fff8d24bd6d - [NSTextView keyDown:] + 658
29 AppKit 0x00007fff8d1f856b - [NSWindow sendEvent:] + 1843
30 AppKit 0x00007fff8d199b32 - [NSApplication sendEvent:] + 3395
31 AppKit 0x00007fff8cfe99f9 - [NSApplication run] + 646
32 AppKit 0x00007fff8cfd4783 NSApplicationMain + 940
33 ResponderExperiment 0x0000000100002de2 main + 34
34 libdyld.dylib 0x00007fff8c5bf5fd start + 1
35因此,也许我可以编写自己的NSArrayController rearrangeObjects:方法,因为我们可以使用NSArrayController的方法来创建一个新的NSArrayController对象,

解决方案

这里有一个可能的解决方案。想法是重新实现文本字段(或更准确地说,字段编辑器服务文本字段)的响应到Tab键作为两个单独的步骤。首先,结束编辑,这将使阵列控制器重新排列其内容。我们通过重置焦点结束编辑,所以我们不在乎阵列控制器可能会发生什么,无论如何焦点。然后,我们自己将焦点从原来聚焦的文本字段推进。



在文本字段上设置委托。在该委托中,实现以下方法:

   - (BOOL)控制:(NSControl *)控制textView:(NSTextView * textView doCommandBySelector:(SEL)command 
{
if(command == @selector(insertTab :))
{
//结束编辑。这将提交编辑的值,并使数组控制器
//重新排列其内容。
[control.window makeFirstResponder:nil];

//这将把焦点放在文本字段中的下一个控件上。
[control.window selectKeyViewFollowingView:control];

//阻止正常处理此命令
return YES;
}

if(command == @selector(insertBacktab :))
{
//结束编辑。这将提交编辑的值,并使数组控制器
//重新排列其内容。
[control.window makeFirstResponder:nil];

//这将从文本字段将焦点放在上一个控件上。
[control.window selectKeyViewPrecedingView:control];

//阻止正常处理此命令
return YES;
}

return NO;
}

有一件事我不知道:远离文本字段,则单击另一个文本字段。阵列控制器在这种情况下是否仍然重置焦点?


I have a master-detail kind of application OS X 10.9 only:
An NSTableView on the left side of the window, the details as NSTextFields on the right side.
I have not set the tab order specifically, out of the box works just fine.

Except after inserting a new object:

  • after inserting a new object the object is selected in the NSTableView.
  • hit tab
  • the first NSTextField is selected
  • write something, hit tab
  • now instead of selecting the next NSTextField nothing is selected,
  • hit tab
  • the NSTableView is selected
  • hit tab
  • the first NSTextField is selected

What i want:

  • after inserting a new object, the first NSTextField of the detail part should be selected
  • hit tab
  • the next NSTextField of the detail part should be selected

UPDATE: I found that the strange behaviour is triggered by enabling NSArrayController’s "Auto Rearrange Content" in Interface Builder. If i disable it, i do not loose my focus anymore. See CoreData-bound NSTableView loses input focus when items change, but only if sorted.

BUT, of course, i still want my content to be automatically sortet — just without loosing my focus during that operation. Can this be done?

UPDATE2: i followed @KenThomases advice and recorded the stack trace at the moment, when my textfield looses keyboard focus:

2014-08-17 16:30:26.003 ResponderExperiment[712:303] (
    0   ResponderExperiment                 0x00000001000014dd -[WMWindow makeFirstResponder:] + 61
    1   AppKit                              0x00007fff8d25c778 -[NSTextView(NSPrivate) _giveUpFirstResponder:] + 257
    2   AppKit                              0x00007fff8d25c56c -[NSTextView(NSKeyBindingCommands) insertTab:] + 270
    3   AppKit                              0x00007fff8d22dc2f -[NSResponder doCommandBySelector:] + 71
    4   AppKit                              0x00007fff8d25b10a -[NSTextView doCommandBySelector:] + 196
    5   AppKit                              0x00007fff8d22d151 -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:] + 1392
    6   AppKit                              0x00007fff8d24c1c2 -[NSTextInputContext handleEvent:] + 845
    7   AppKit                              0x00007fff8d22b9dd -[NSView interpretKeyEvents:] + 180
    8   AppKit                              0x00007fff8d24bd6d -[NSTextView keyDown:] + 658
    9   AppKit                              0x00007fff8d1f856b -[NSWindow sendEvent:] + 1843
    10  AppKit                              0x00007fff8d199b32 -[NSApplication sendEvent:] + 3395
    11  AppKit                              0x00007fff8cfe99f9 -[NSApplication run] + 646
    12  AppKit                              0x00007fff8cfd4783 NSApplicationMain + 940
    13  ResponderExperiment                 0x0000000100002de2 main + 34
    14  libdyld.dylib                       0x00007fff8c5bf5fd start + 1
    15  ???                                 0x0000000000000003 0x0 + 3
)
2014-08-17 16:30:26.014 ResponderExperiment[712:303] (
    0   ResponderExperiment                 0x00000001000014dd -[WMWindow makeFirstResponder:] + 61
    1   AppKit                              0x00007fff8d03c918 -[NSControl abortEditing] + 83
    2   AppKit                              0x00007fff8d2723e0 -[NSValueBinder discardEditing] + 162
    3   AppKit                              0x00007fff8d1aee30 -[NSController discardEditing] + 115
    4   AppKit                              0x00007fff8d1af971 -[NSArrayController rearrangeObjects] + 27
    5   AppKit                              0x00007fff8d3697a9 -[NSArrayController observeValueForKeyPath:ofObject:change:context:] + 294
    6   AppKit                              0x00007fff8d39ac08 -[NSArrayController _setMultipleValue:forKeyPath:atIndex:] + 323
    7   AppKit                              0x00007fff8d39ba12 -[NSArrayController _setSingleValue:forKeyPath:] + 137
    8   Foundation                          0x00007fff8bf9e19a -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 285
    9   AppKit                              0x00007fff8d25444c -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 364
    10  AppKit                              0x00007fff8d254287 -[NSBinder setValue:forBinding:error:] + 245
    11  AppKit                              0x00007fff8d74c4ee -[NSValueBinder _applyObjectValue:forBinding:canRecoverFromErrors:handleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:] + 194
    12  AppKit                              0x00007fff8d74c871 -[NSValueBinder applyDisplayedValueHandleErrors:typeOfAlert:canRecoverFromErrors:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:error:] + 621
    13  AppKit                              0x00007fff8d74c9d4 -[NSValueBinder _applyDisplayedValueIfHasUncommittedChangesWithHandleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:error:] + 127
    14  AppKit                              0x00007fff8d253c2e -[NSValueBinder validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:] + 436
    15  AppKit                              0x00007fff8d253a57 -[_NSBindingAdaptor _validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:bindingAdaptor:] + 160
    16  AppKit                              0x00007fff8d25399d -[_NSBindingAdaptor validateAndCommitValueInEditor:editingIsEnding:errorUserInterfaceHandled:] + 260
    17  AppKit                              0x00007fff8d25e0ba -[NSTextField textShouldEndEditing:] + 402
    18  AppKit                              0x00007fff8d25dc63 -[NSTextView(NSSharing) resignFirstResponder] + 393
    19  AppKit                              0x00007fff8d136170 -[NSWindow makeFirstResponder:] + 455
    20  ResponderExperiment                 0x000000010000154c -[WMWindow makeFirstResponder:] + 172
    21  AppKit                              0x00007fff8d25c778 -[NSTextView(NSPrivate) _giveUpFirstResponder:] + 257
    22  AppKit                              0x00007fff8d25c56c -[NSTextView(NSKeyBindingCommands) insertTab:] + 270
    23  AppKit                              0x00007fff8d22dc2f -[NSResponder doCommandBySelector:] + 71
    24  AppKit                              0x00007fff8d25b10a -[NSTextView doCommandBySelector:] + 196
    25  AppKit                              0x00007fff8d22d151 -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:] + 1392
    26  AppKit                              0x00007fff8d24c1c2 -[NSTextInputContext handleEvent:] + 845
    27  AppKit                              0x00007fff8d22b9dd -[NSView interpretKeyEvents:] + 180
    28  AppKit                              0x00007fff8d24bd6d -[NSTextView keyDown:] + 658
    29  AppKit                              0x00007fff8d1f856b -[NSWindow sendEvent:] + 1843
    30  AppKit                              0x00007fff8d199b32 -[NSApplication sendEvent:] + 3395
    31  AppKit                              0x00007fff8cfe99f9 -[NSApplication run] + 646
    32  AppKit                              0x00007fff8cfd4783 NSApplicationMain + 940
    33  ResponderExperiment                 0x0000000100002de2 main + 34
    34  libdyld.dylib                       0x00007fff8c5bf5fd start + 1
    35  ???                                 0x0000000000000003 0x0 + 3
)

So perhaps I could write my own NSArrayController rearrangeObjects: method, that does not loose focus?

解决方案

Here's a possible solution. The idea is to re-implement the response of the text field (or, more accurately, the field editor serving the text field) to the Tab key as two separate steps. First, end editing, which will make the array controller rearrange its content. We end editing by resetting focus, so we don't care what the array controller may happen to do to focus anyway. Then, advance the focus from the originally-focused text field ourselves.

Set a delegate on your text fields. In that delegate, implement the following method:

- (BOOL) control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)command
{
    if (command == @selector(insertTab:))
    {
        // End editing. This will commit the edited value and cause the array controller
        // to rearranged its contents.
        [control.window makeFirstResponder:nil];

        // This will put focus on the next control from the text field.
        [control.window selectKeyViewFollowingView:control];

        // Prevent the normal processing of this command
        return YES;
    }

    if (command == @selector(insertBacktab:))
    {
        // End editing. This will commit the edited value and cause the array controller
        // to rearranged its contents.
        [control.window makeFirstResponder:nil];

        // This will put focus on the previous control from the text field.
        [control.window selectKeyViewPrecedingView:control];

        // Prevent the normal processing of this command
        return YES;
    }

    return NO;
}

One thing I'm not sure of: what happens if instead of Tab-ing away from the text field, you click on another text field. Does the array controller still reset focus in that case?

这篇关于启用NSArrayController“自动重新排列内容”时,插入和编辑新对象后,键盘焦点丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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