Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSManagedObjectContext save causes NSTextField to lose focus

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?

like image 791
Tony Arnold Avatar asked Dec 17 '22 21:12

Tony Arnold


2 Answers

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.

like image 65
Axel Avatar answered Mar 08 '23 02:03

Axel


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;
}
like image 42
cocoafan Avatar answered Mar 08 '23 03:03

cocoafan