Подтвердить что ты не робот

Каков новый способ привязки NSArrayController к контексту управляемых объектов документа Core Data?

До того, как Xcode отправился и добавил Storiesboards для приложений OS X, вы могли подключить контроллер массива к контексту объекта, управляемого документом, привязав Managed Object Context контроллера массива к File Owner с помощью Model Key Path of managedObjectContext. С раскадровками больше нет File Owner, так откуда вы теперь получаете контекст?

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

4b9b3361

Ответ 1

Итак, у меня есть ответ от Apple. Это относится к приложениям с базовыми данными на основе документов, код все в Swift, но идея одинаков в Objective-C вам просто нужно перевести.

Первый ответ, который они мне дали, - связать контроллер массива с контроллером представления, который запускает представление с помощью пути ключа модели self.view.window.windowController.document.managedObjectContex. Образец, который я показал, использовал этот метод и вообще не имел сообщений об ошибках, однако он был единственным контроллером представления внутри оконного контроллера с одним контроллером массива. Моя настройка - это окно в представление табуляции к представлениям с двумя контроллерами массива в одной сцене. Я все еще получал Cannot perform operation without a managed object context каждый раз, когда новый документ был открыт или создан. Второе решение, которое работало для меня, состояло в том, чтобы по-прежнему привязывать контроллер массива к контроллеру представления, но с путём ключа модели self.representedObject.managedObjectContext, а затем добавить в конец функции класса документа makeWindowControllers():

override func makeWindowControllers() {
……
    let tabViewController = windowController.contentViewController as NSTabViewController
    for object in tabViewController.childViewControllers {
        let childViewController = object as NSViewController
        childViewController.representedObject = self
    }
}

Это решило проблему для меня. Надеюсь, здесь будет достаточно информации, чтобы показать, когда другие google эту проблему.

Ответ 2

Используя созданный по умолчанию Xcode-проект и включая CoreData помещает член managedObjectContext в AppDelegate. Вы можете добавить следующий код в свой ViewController, а затем использовать managedObjectContext как "путь ключа модели" с привязкой к ViewController для вашего NSArrayController.

lazy var managedObjectContext: NSManagedObjectContext = { 
    return (NSApplication.sharedApplication().delegate
        as? AppDelegate)?.managedObjectContext }()!

Это просто создает член, который перенаправляет туда, где хранится ваш фактический MOC. Это полезно, потому что привязка NSArrayController происходит до viewDidLoad(), поэтому почему член экземпляра не будет достаточным. Кроме того, если вы хотите реорганизовать одноуровневый класс CoreDataManager, вы можете просто изменить, куда перенаправить. Кроме того, вы можете добавить это как расширение класса, чтобы все ViewControllers могли получить доступ к вашему MOC.

Objective-C версия по запросу:

@interface MyViewController ()

@property (nonatomic, readonly) NSMangedObjectContext* managedObjectContext;

@end

@implementation MyViewController

- (NSManagedObjectContext*)managedObjectContext
{
    return ((AppDelegate*)([NSApplication sharedApplication].delegate)).managedObjectContext;
}

...

@end

Ответ 3

Вы всегда могли связываться через NSApplication с помощью ключевого пути delegate.managedObjectContext, если делегат приложения владеет базовым стеком данных. В противном случае вы могли бы передать MOC через каждый контроллер представления с свойством MOC на каждом из них, что настоятельно рекомендуется тем, кто утверждает, что делегат приложения не должен использоваться для владения одномодовыми MOC и что есть еще одна полезность в возможности чтобы обеспечить каждому VC отдельный MOC.

Я считаю, что вы также можете создать экземпляр MOC в раскадровке в IB. По крайней мере, всегда был объект MOC для перьев. Хотя я не использовал этого достаточно, чтобы знать, как он относится к программным основным стекам данных. Вероятно, лучше просто иметь свойство MOC где-нибудь, где вы можете получить доступ либо в иерархии VC, либо в делегате приложения

Ответ 4

Обновлено:

@theMikeSwan, ну, это почти работает для меня. Вот что я имею:

OSX EL Capitan GM Xcode 7GM и Xcode 7.1 beta​​p >

Стандартное приложение Coredata/Document

Заменил MainViewController с помощью TabViewController и добавил к нему 2 ViewControllers.

Добавлен в ваш код, чтобы поместить createdObject во все контроллеры представлений в tabviewcontroller.

Вкладка one - это контроллер представления с таблицей, а контроллер массива, привязанный к объекту с именем Profiles, и tableview привязан к этому контроллеру с +/- и т.д.

Вкладка two - это представление с контроллером представления с таблицей, а контроллер массива, привязанный к объекту под названием Commands, и tableview привязан к этому контроллеру.

Между объектами "Профили" и "Команды" существует отношение "один-много" с командами профилей имен и lt. → > .

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

Далее я хочу применить отношение "один ко многим", то есть, если я выберу профиль в таблице на вкладке 1, а затем переключится на вкладку два, я хочу видеть только команды, связанные с выбранным профилем в этой таблице. Это не работает. Все введенные команды показаны во всех случаях, я пробовал предикаты фильтров, извлекал предикаты и т.д. С различной степенью катастрофы.

Я пробовал все, что мог придумать, и много хаков, о которых я бы не сказал -

В этот момент я добавил второй массив Controller ко второму представлению вкладки и привязал его к объекту Profiles и к self.representedObject.managedObjectContext и т.д. Я добавил NSTextField во второе представление вкладки и привязал его к только что добавленному profileArrayController → selection → name, чтобы увидеть, что думал контроллер...

Имя Profile- > во второй вкладке никогда не изменяется независимо от того, что я выбираю в первой таблице табуляции, он всегда показывает то же имя Profiles- > . Команды, перечисленные в таблице на второй вкладке, не зависят от выбора в первой таблице.

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

спасибо Франк

Отредактировано для добавления:

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