2013-04-11 2 views
1

У меня есть NSTableView, значение NSTableColumn которого привязано к NSArrayController. Контроллер arrayController управляет набором объектов в моем основном контексте объектов, управляемых данными.NSArrayController, создавая объекты CoreData программно, и KVO

Он работает хорошо, и когда новые объекты вставляются в массив Controller через действия пользовательского интерфейса, tableView выбирает новый элемент.

Однако я хотел бы создать новые объекты в moc программно, а затем выбрать новый объект в arrayController.

Я попытался следующие:

Image *newImage = [Image newImage]; // convenience method to insert new entity into mod. 
newImage.title = [[pathToImage lastPathComponent] stringByDeletingPathExtension]; 
newImage.filename = [pathToImage lastPathComponent]; 

[self.primaryWindowController showImage:newImage]; 

ShowImage: метод, как так:

- (void)showImage:(Image *)image 
{ 
    [self.imagesArrayController fetch:self]; 
    [self.imagesArrayController setSelectedObjects:@[image]]; 
} 

Однако arrayController не меняет свой выбор.

Я делаю это неправильно? Я предполагаю, что объект newImage, который я создал в moc, совпадает с объектом, которым управляет arrayController. Если это правда, почему переменная arrayController не меняет свой выбор?

Хмм - проверяя это предположение, я теперь проверил содержимое arrayController во время выполнения. Новое изображение нет - что я предполагаю, что означает, что я «пошел за спиной» привязок вручную путем вставки в МОС ...

Моего newImage удобного метода является, как так:

+ (Image *)newImage 
{ 
    Image *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:[[CoreDataController sharedController] managedObjectContext]]; 
    return newImage; 
} 

Разве это не соответствует требованиям KVO?

хммм - Edit 2 ...

Я предполагаю, что это KVO соответствует, так как новое изображение отображается в пользовательском интерфейсе. Теперь я думаю, что существует задержка между вставкой объекта в moc и сообщением arrayController.

I See from this question New Core Data object doesn't show up in NSArrayController arrangedObjects (с полезной ссылкой справа от этого вопроса SO), в котором запрашивается массивController: должен помочь обновить arrayController, но фактическая выборка не произойдет до следующего раза runloop работает.

Должен ли я откладывать выбор нового объекта с помощью таймера? Это кажется немного безвкусным ...

ответ

2

Право - решить ее, благодаря этому вопросу: New Core Data object doesn't show up in NSArrayController arrangedObjects

я должен был назвать processPendingChanges: на MOC непосредственно после установки нового объекта.

Итак, мой новый удобный метод создания теперь:

+ (Image *)newImage 
{ 
    Image *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:[[CoreDataController sharedController] managedObjectContext]]; 
    [[[CoreDataController sharedController] managedObjectContext] processPendingChanges]; 
    return newImage; 
} 
+0

У вас есть класс 'coreDataController sharedController '' class. Почти как если бы это было похоже на одноэлементный класс, если вы не возражаете, не могли бы вы поделиться этим классом CoreDataController, который у вас есть в репозитории git? Это было бы очень полезно для таких людей, как я и многие другие, которые попадают в Core Data. Увидеть практический пример было бы очень полезно. Спасибо Diggory – Pavan

+0

На самом деле нет необходимости в таком «coreDataController», поскольку API CoreData достаточно ясен, и вы используете их из многих мест в своем приложении, нет смысла централизовать вызовы CoreData на один конкретный контроллер. Кроме того, в приведенном выше примере лучшей реализацией было бы взятие управляемых объектов из самого нового объекта, а не из какого-то несопоставимого контроллера, чей контекст может отличаться. (например, в приложениях на основе документов контроллер окна документа имеет mangedObjectContext) –

0

Если вы хотите сделать это программно, проще всего непосредственно добавить новый объект сущности к NSArrayController, так же легко, как:

[self.imagesArrayController addObject:newImage]; 

Это будет хитрость как добавления объекта к контроллеру, так и его выбора.

Один сбой - я не знаю, какой вид (NSView, UIView) используется для представления содержимого NSArrayController, но NSTableView не будет автоматически прокручивать себя, чтобы открыть вновь добавленный элемент.

мне пришлось отложить это (как добавление происходит в более позднем runloop) как так:

NSUndoManager *um = self.managedObjectContext.undoManager; 
[um beginUndoGrouping]; 
[um setActionName:NSLocalizedString(@"New Sample", NULL)]; 
PMWaterSample *sampleToAdd = [self createNewSample]; 
[self.samplesController addObject:sampleToAdd]; 

// Actual addition is deferred, hence we delay the scrolling too, on the main-thread's queue. 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.samplesController rearrangeObjects]; 

    // bring last row (newly added) into view 
    NSUInteger selectedIdx = [self.samplesController selectionIndex]; 
    if (selectedIdx != NSNotFound) { 
     [self.samplesTable scrollRowToVisible:selectedIdx]; 
    } 
    [um endUndoGrouping]; 
}); 

Надеется, что поможет. Мне никогда не приходилось вынуждать MOC обрабатывать PendingChanges. Я все еще живу с чувством, что есть лучший способ сделать это, и заставить контроллер массива сделать свой элемент вложения элементов пользовательского интерфейса прокруткой и открыть новый элемент, но я не знаю, как это сделать.

 Смежные вопросы

  • Нет связанных вопросов^_^