Каков новый способ привязки NSArrayController к контексту управляемых объектов документа Core Data?
До того, как Xcode отправился и добавил Storiesboards для приложений OS X, вы могли подключить контроллер массива к контексту объекта, управляемого документом, привязав Managed Object Context
контроллера массива к File Owner
с помощью Model Key Path
of managedObjectContext
. С раскадровками больше нет File Owner
, так откуда вы теперь получаете контекст?
Документация Apple в этой области отстает, и нет никаких очевидных мест для привязки в Xcode. Очевидно, я могу просто вернуться к маршруту без раскадровки и использовать старый метод, но должен быть новый способ сделать это.
Ответы
Ответ 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 betap >
Стандартное приложение 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, на который ссылается первая вкладка. Но это просто чувство. Я потерял, какие-либо предложения о том, как сделать отношение "один-много" между вкладками в настройках контроллера отображения с несколькими вкладками, например, это?
спасибо
Франк
Отредактировано для добавления:
Кстати, у меня есть на некоторых из этих вкладок, например, в командной вкладке несколько таблиц, настроенных с одним или несколькими отношениями на одной и той же вкладке, которые работают правильно - например, у меня есть таблица синонимов со связями с сущностью синонимов через контроллер массива которая представляет собой много сторон корабля отношения с объектом команды. Он отлично работает, пока таблицы/контроллеры массива находятся на одной вкладке, но когда на отдельных вкладках это не радость.