Cocoa NSManagedObjectContext保存导致NSTextField失去焦点

Cocoa NSManagedObjectContext保存导致NSTextField失去焦点,cocoa,macos,core-data,focus,nstextfield,Cocoa,Macos,Core Data,Focus,Nstextfield,这是我在应用程序中看到的一个非常奇怪的问题。我有一个绑定到NSManagedObject属性的NSTextField,但每当保存该对象时,textfield就会失去焦点。我在不断更新绑定的值,所以这远远不是理想的 以前有没有人见过类似的情况,并且(希望)找到了解决方案?好的,感谢Martin指出我应该更仔细地阅读文档。这是预期的行为,以下是我为避免这种情况所做的工作(根据您的判断,这是否适合您): 我每3秒钟保存一次上下文,在开始时检查上下文是否有任何更改,然后对我的NSManagedObjec

这是我在应用程序中看到的一个非常奇怪的问题。我有一个绑定到NSManagedObject属性的NSTextField,但每当保存该对象时,textfield就会失去焦点。我在不断更新绑定的值,所以这远远不是理想的


以前有没有人见过类似的情况,并且(希望)找到了解决方案?

好的,感谢Martin指出我应该更仔细地阅读文档。这是预期的行为,以下是我为避免这种情况所做的工作(根据您的判断,这是否适合您):

我每3秒钟保存一次上下文,在开始时检查上下文是否有任何更改,然后对我的
NSManagedObjectContext
执行实际的
save:
方法。我向我的核心数据控制器类添加了一个简单的递增/递减
NSUInteger
\u saveDisabler
)类,该类通过以下方法进行修改:

- (void)enableSaves {
    if (_saveDisabler > 0) {
        _saveDisabler -= 1;
    }   
}

- (void)disableSaves {
    _saveDisabler += 1;
}
- (void)textDidBeginEditing:(NSNotification *)notification;
- (void)textDidEndEditing:(NSNotification *)notification;
然后,我在自定义的
saveContext
方法中所做的就是在顶部执行一个简单的检查:

if (([moc hasChanges] == NO) || (_saveDisabler > 0)) {
    return YES;
}
这可以防止保存发生,并且意味着焦点不会从我的任何自定义textfield子类中被窃取。为完整起见,我还通过以下方法将NSTextField子类化,并在我的Core Data controller中启用/禁用保存:

- (void)enableSaves {
    if (_saveDisabler > 0) {
        _saveDisabler -= 1;
    }   
}

- (void)disableSaves {
    _saveDisabler += 1;
}
- (void)textDidBeginEditing:(NSNotification *)notification;
- (void)textDidEndEditing:(NSNotification *)notification;

这可能有点混乱,但对我来说很有效。如果有人用另一种方法成功地做到了这一点,我很想听到更干净/不太复杂的方法。

我最近遇到了这个问题,并通过更改NSTextField绑定到NSManagedObject属性的方式来修复它。我没有将文本字段的值绑定到NSArrayController的selection.[attribute]键路径,而是绑定了视图控制器的arrayController.selection.[attribute]键路径,该视图控制器具有指向控制器的正确出口


出于某种原因,如果以这种方式绑定,则在保存NSManagedObjectContext时,NSTextField不会失去焦点。

我想分享我的解决方案。它将适用于所有字段,无需修改。 我已经为这个帖子优化了它,删除了一些错误检查、日志记录和线程安全

- (BOOL)saveChanges:(NSError **)outError {
  BOOL result = YES;
  @try {
    NSError *error = nil; 
    if ([self hasChanges])  {

    // Get field editor
    NSResponder *responder = [[NSApp keyWindow] firstResponder];
    NSText *editor = [[NSApp keyWindow] fieldEditor: NO forObject: nil];
    id editingObject = [editor delegate];
    BOOL isEditing = (responder == editor);
    NSRange range;
    NSInteger editedRow, editedColumn;

   // End editing to commit the last changes
   if (isEditing) {

     // Special case for tables
     if ([editingObject isKindOfClass: [NSTableView class]]) {
       editedRow = [editingObject editedRow];
       editedColumn = [editingObject editedColumn];
     }

     range = [editor selectedRange];
     [[NSApp keyWindow] endEditingFor: nil];
   }

   // The actual save operation
   if (![self save: &error]) {
     if (outError != nil)
        *outError = error;
      result = NO;
    } else {
      result = YES;
    }

    // Now restore the field editor, if any.
    if (isEditing) {
      [[NSApp keyWindow] makeFirstResponder: editingObject];
      if ([editingObject isKindOfClass: [NSTableView class]])
        [editingObject editColumn: editedColumn row: editedRow withEvent: nil select: NO];
        [editor setSelectedRange: range];
      }
    }
  } @catch (id exception) {
    result = NO;
  }
  return result;
}

您是否保存每次更改的上下文?文本字段失去焦点是NSManagedObjectContext保存的正常行为。检查NSEditor协议以获取更多信息并非每次更改都如此-它设置为在定时延迟时保存,并且仅在上下文发生更改时保存。我不知道NSEditor协议-我必须重新考虑一下-谢谢!我使用10.7附带的自动保存功能,用于基于NSPersistentDocument的应用程序。既然保存操作是自动处理的,我的文本字段总是在键入两个字符后失去焦点。也许我遗漏了什么,但我认为应该有一个简单的解决办法。有什么建议吗?当然,编辑点可能不在末尾(或者甚至可能有选择)。只需在结束编辑之前捕获[editor selectedRange]NSRange,然后使用保存的NSRange捕获[editor setSelectedRange:],您说得对。我已经改进了代码并添加了对NSTableView的支持。我现在编辑了我的答案,与大家分享。请注意,这是我实际代码的精简版本,其中还包括线程安全和错误处理。缺点是,如果用户习惯于将光标始终保留在文本字段中,您将永远无法保存。我通常会将我所有的textfields/tokefields/等绑定设置为持续更新,然后使用类似于@cocoafan的方法来恢复第一响应者和选择。这也解决了我的问题。我在过去已经使用过那些解耦绑定的技巧。我想知道是否有人看到了真正的问题。在我看来,这应该没问题(显然,如果只有一个UI可以更改TextField的底层核心数据属性的话)!当文本字段位于表视图中的文本字段单元格内时,您会怎么做?我的问题与@Sbhklr相同,我的文本字段位于基于视图的NSTableView中的视图内。