NSManagedObjectContext 保存导致 NSTextField 失去焦点

发布于 2024-09-25 20:25:52 字数 148 浏览 8 评论 0原文

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

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

This is a really strange problem I'm seeing in my app. I have an NSTextField bound to an attribute of an NSManagedObject, but whenever the object is saved the textfield loses focus. I'm continuously updating the value of the binding, so this is far from ideal.

Has anyone seen anything like this before, and (hopefully) found a solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美煞众生 2024-10-02 20:25:52

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

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

I encountered the issue recently and fixed it by changing the way the NSTextField was bound to the NSManagedObject attribute. Instead of binding the value of the text field to the selection.[attribute] key path of the NSArrayController, I bound the arrayController.selection.[attribute] keyPath of the view controller that had a proper outlet pointing to the controller.

For some reason, the NSTextField doesn't loose focus when the NSManagedObjectContext is saved if bound this way.

初相遇 2024-10-02 20:25:52

我想分享我的解决方案。无需修改即可适用于所有领域。
我针对这篇文章对其进行了优化,并删除了一些错误检查、日志记录和线程安全。

- (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;
}

I want to share my solution. It will work for all fields without modification.
I have optimized it for this posting and removed some error checking, logging and thread safety.

- (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;
}
预谋 2024-10-02 20:25:52

好的,感谢马丁指出我应该更仔细地阅读文档。这是预期的行为,这就是我为解决这个问题所做的事情(根据您的判断来判断这是否适合您):

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

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

- (void)disableSaves {
    _saveDisabler += 1;
}

然后我在自定义 saveContext 中执行的所有操作 方法是在顶部进行简单的检查:

if (([moc hasChanges] == NO) || (_saveDisabler > 0)) {
    return YES;
}

这可以防止保存发生,并且意味着焦点不会从我的任何自定义文本字段子类中被窃取。为了完整起见,我还对 NSTextField 进行了子类化,并通过以下方法启用/禁用了我的核心数据控制器中的保存:

- (void)textDidBeginEditing:(NSNotification *)notification;
- (void)textDidEndEditing:(NSNotification *)notification;

它可能有点混乱,但它对我有用。如果有人以另一种方式成功地做到了这一点,我很想听到更干净/更简单的方法。

OK, so thanks to Martin for pointing out that I should read the docs a little more closely. This is expected behaviour, and here's what I did to get around it (use your judgement as to whether this is appropriate for you):

I save my context once every 3 seconds, checking at the start if the context has any changes before I bother executing the actual save: method on my NSManagedObjectContext. I added a simple incrementing/decrementing NSUInteger (_saveDisabler) to my Core Data controller class that is modified via the following methods:

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

- (void)disableSaves {
    _saveDisabler += 1;
}

Then all I do in my custom saveContext method is do a simple check at the top:

if (([moc hasChanges] == NO) || (_saveDisabler > 0)) {
    return YES;
}

This prevents the save from occurring, and means that the focus is not stolen from any of my custom textfield subclasses. For completeness, I also subclassed NSTextField and enable/disable saves in my Core Data controller from the following methods:

- (void)textDidBeginEditing:(NSNotification *)notification;
- (void)textDidEndEditing:(NSNotification *)notification;

It might be a little messy, but it works for me. I'm keen to hear of cleaner/less convoluted methods if anyone has done this successfully in another way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文