2015-01-28 1 views
12

Перед тем, как Xcode пошел и добавил раскадровки для приложений OS X, вы могли бы подключить контроллер массива к контексту управляемого объекта вашего документа, привязав Managed Object Context контроллера массива к File's Owner с Model Key Path из managedObjectContext. С раскадными версиями больше нет File's Owner, так где же вы теперь получаете контекст?Каков новый способ привязки NSArrayController к контексту управляемого объекта документа Core Data?

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

ответ

10

Так что у меня есть ответ от 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 эту проблему.

+0

Моя проблема заключается в том, что управляемый объект Object для контроллера объекта в контроллере представления раскадровки запрашивается во время let windowController = storyboard.instantiateControllerWithIdentifier («Document Window Controller») как! Вызов NSWindowController до того, как у меня появится возможность установить для объекта представленный объект. – AutomatonTec

1

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

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

+0

Я пробовал передать MOC через розетку, которая была экземпляром IB для «NSManagedObjectContext», и я устал передавать «NSPersistentDocument» и привязываться к ней, ни один из них не работал, поэтому я подал инцидент с DTS. Я могу попробовать просто пропустить MOC и не иметь его в конце, может заставить управление-перетащить, чтобы привязать работу лучше. – theMikeSwan

+0

Мое понимание заключается в том, что добавление объекта MOC в IB будет фактически распределять MOC, который будет принадлежать представлению, и который будет выпущен, когда представление будет освобождено. И привязки к этому объекту, скорее всего, указывают на объект, которым обладает представление, независимо от того, пытаетесь ли вы указать свойство IBOutlet на другой MOC, который вы создаете программно, - объекты в представлении привязаны к MOC в представлении. Я считаю, что для делегата приложения или одного из контроллеров проще создать MOC и связать его через контроллер (ы). – stevesliva

+0

Да, я был уверен, что MOC, добавленные мной в IB, не были изменены на один из документа, хотя я использовал выход, чтобы установить их. Я также просил об этом в форумах Apple Dev и получил ответ, который почти работает: привяжите MOC контроллера массива к контроллеру представления, который запускает его с помощью ключевого пути 'view.window.windowController.document.managedObjectContext'. Я по-прежнему вижу одну жалобу на каждую загружаемую вкладку, но после этого она работает. Лучшая часть - до сих пор нет кода для получения простого простого приложения на основе данных Core Data! – theMikeSwan

8

Использование проекта сгенерированного 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 
+0

@Chapman: Можете ли вы перевести свой пример на цель c –

+1

@ user3175421: Обновлен с версией Obj-C. Не совсем лаконично;) –

+0

Не совсем лаконично, но много, гораздо читабельнее! Или в другой пунктуации: return [(AppDelegate *) [[NSApplication sharedApplication] delegate] managedObjectContext]; –

1

Обновлено:

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

OSX EL Capitan GM Xcode 7GM и Xcode 7.1 бета

Стандартный CoreData/Документ приложения

Заменено MainViewController с TabViewController и добавил 2 ViewControllers к этому.

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

Вкладка один контроллер вид со столом, а контроллер массива, который связан с объект, называемый Профили и TableView связывается с этим контроллером с +/- и т.д.

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

Между объектами «Профили» и «Команды» существует отношение «один-много» с профилями имен < - >> команд.

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

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

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

На данный момент я добавил второй arrayController на второй взгляд вкладки и сковал его Profiles лица и self.representedObject.managedObjectContext и т. д. Я добавил NSTextField на второе представление вкладки и привязал его к только что добавленному профилю profileArrayController -> selection ->, чтобы узнать, что думал контроллер ...

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

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

благодаря Frank

Edited добавить:

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

+0

Взгляните на часть моего ответа, в которой упоминается привязка к 'self.representedObject.managedObjectContext'. Обязательно также используйте показанный код. У меня также возникли проблемы при использовании представления табуляции в мире данных с данными на основе документов. @ marcus-s-zarra написал книгу о Core Data, и вы можете найти несколько сообщений в своем блоге об этом. У меня есть несколько гораздо более скудных сообщений, которые в наши дни довольно стары, но по-прежнему имеют полезную информацию в них на www.theMikeSwan.com/blog/. Это, возможно, лучше служило новым вопросом кстати. – theMikeSwan

+0

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

+0

Оба контроллера массива видят одни и те же данные на уровне MOC, проблема в том, что выбор хранится в контроллере массива, а не в MOC. Чтобы выбор на одной вкладке повлиял на то, что показано на другой вкладке, вам нужно будет добавить что-то, вероятно, в любом открытом супер-представлении или оконном контроллере между вкладками, чтобы отслеживать выбор на основной вкладке, чтобы два вкладки имеют канал связи. В качестве альтернативы вы можете добавить объект к своей модели, который просто отслеживает выбранный элемент, а затем использовать его для управления тем, что показано на второй вкладке. – theMikeSwan

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