Сохранение NSManagedObjectContext приводит к потере фокуса NSTextField - PullRequest
4 голосов
/ 30 сентября 2010

Это действительно странная проблема, которую я вижу в своем приложении. У меня есть NSTextField, связанный с атрибутом NSManagedObject, но всякий раз, когда объект сохраняется, текстовое поле теряет фокус. Я постоянно обновляю значение привязки, так что это далеко от идеала.

Кто-нибудь видел что-то подобное раньше и (надеюсь) нашел решение?

Ответы [ 3 ]

5 голосов
/ 16 сентября 2011

Недавно я столкнулся с проблемой и исправил ее, изменив способ, которым NSTextField был связан с атрибутом NSManagedObject.Вместо привязки значения текстового поля к ключевому пути selection. [Attribute] NSArrayController, я связал arrayController.selection. [Attribute] keyPath контроллера представления, у которого был правильный вывод, указывающий на контроллер.

По какой-то причине NSTextField не теряет фокус, когда NSManagedObjectContext сохраняется при привязке таким образом.

4 голосов
/ 30 октября 2011

Я хочу поделиться своим решением. Он будет работать для всех полей без изменений. Я оптимизировал его для этой публикации и удалил некоторые проверки ошибок, ведение журнала и безопасность потоков.

- (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;
}
3 голосов
/ 30 сентября 2010

ОК, поэтому спасибо Мартину за то, что он указал, что я должен прочитать документы немного более внимательно.Это ожидаемое поведение, и вот что я сделал, чтобы обойти это (используйте ваше суждение относительно того, подходит ли это вам):

Я сохраняю свой контекст каждые 3 секунды, проверяя в начале, если контекстесть какие-либо изменения, прежде чем я удосужился выполнить фактический save: метод на моем NSManagedObjectContext.Я добавил простое увеличение / уменьшение NSUInteger (_saveDisabler) в свой класс контроллера базовых данных, который изменяется с помощью следующих методов:

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

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

Затем все, что я делаю в своем пользовательском методе saveContext, этовыполните простую проверку сверху:

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

Это предотвращает сохранение и означает, что фокус не украден ни у одного из моих пользовательских подклассов текстового поля.Для полноты я также разделил NSTextField на подклассы и включил / отключил сохранение в моем контроллере Core Data из следующих методов:

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

Это может быть немного грязно, но это работает для меня.Я хотел бы услышать о более чистых / менее запутанных методах, если кто-то сделал это успешно другим способом.

...