2016-06-13 2 views
0

Я разрабатываю приложение Mac в Xcode 7.3.1. и я пытаюсь передать Контекст объекта модели из моего AppDelegate в ArrayController.OS X Основные данные - Передача управляемого объекта Контекст в контроллер просмотра

У меня есть класс с именем DataController, который создает мой стек Core Data. DataController.managedObjectContext содержит контекст управляемого объекта.

Мой класс AppDelegate выглядит следующим образом:

class AppDelegate: NSObject, NSApplicationDelegate { 

    var dataController: DataController! 

    func applicationDidFinishLaunching(aNotification: NSNotification) { 
    // Insert code here to initialize your application 

    // Create an instance of the DataController class. 
    dataController = DataController() 

    // Create a reference to the first ViewController embedded in the WindowController. 
    guard let splitViewController = NSApplication.sharedApplication().windows[0].contentViewController as? ManagedObjectContextSettable 
     else { fatalError("Wrong view controller type")} 

    // Set the managedObjectContext property. 
    splitViewController.managedObjectContext = dataController.managedObjectContext 
    } 

    func applicationWillTerminate(aNotification: NSNotification) { 
    // Insert code here to tear down your application 
    } 

} 

В моей раскадровки я встроил SplitViewController в моем WindowController. У SplitViewController есть свой собственный класс контроллера View с именем SplitViewController. Вот код в SplitViewController:

class SplitViewController: NSSplitViewController, ManagedObjectContextSettable { 

    var managedObjectContext: NSManagedObjectContext! 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do view setup here. 


    // Create a reference to the first ViewController embedded in the WindowController. 
    let childControllers = self.childViewControllers 

    print("childControllers.count = \(childControllers.count)") 

    for childController in childControllers{ 

     if childController.isKindOfClass(TableViewController){ 

      print("Found TableViewController") 

      guard let tableViewController = childController as? ManagedObjectContextSettable 
       else { fatalError("Wrong view controller type")} 

      tableViewController.managedObjectContext = managedObjectContext 

     } 
    } 
    } 
} 

В одном из Split View Items мой TableView, который имеет свой собственный View Controller с именем TableViewController. Вот код для TableViewController:

class TableViewController: NSViewController, ManagedObjectContextSettable, NSTableViewDataSource, NSTableViewDelegate { 

    @IBOutlet weak var tableView: NSTableView! 

    var managedObjectContext: NSManagedObjectContext! 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do view setup here. 
    //print(managedObjectContext.description) 
    } 

} 

В раскадровке я тащил в ArrayController и на вкладке Bindings инспектора Я дал Bind To и выбранный TableViewController и установить модель Key Путь к «self.managedObjectContext». В конечном итоге он не получает контекст управляемого объекта.

Я не могу установить, следует ли переопределить функцию prepareForSegue для встроенного ViewController, каждый пример, который я прочитал для IOS.

Куда я ошибся, пожалуйста?

ответ

0

applicationDidFinishLaunching может быть выполнен после viewDidLoad. Задайте managedObjectContext childControllers, когда установлен параметр managedObjectContext splitViewController.

Привязки используют KVO. Измените var managedObjectContext на dynamic var managedObjectContext, чтобы сделать собственность KVO совместимой.

+0

Я заметил, что AppDelegate.applicationDidFinishLoading был выполнен после всех методов viewDidLoad ViewController. Предлагаете ли вы установить переменную managedObjectContext в дочернем контроллере представления SplitViewController (TableViewController) в методе AppDelegate.applicationDidFinishLoading? – TDC

+0

Я предлагаю 'viewDidLoad'' SplitViewController' может быть выполнен до 'viewDidLoad'' TableViewController'. Внедрите установщик 'managedObjectContext' и распространите его на childControllers. – Willeke

+0

Другим возможным решением является привязка 'managedObjectContext' к контроллерам массивов программно к' dataController.managedObjectContext'. (Я думаю, что разработчики раскадровки и контроллеры просмотров никогда не слышали о привязках) – Willeke

0

Если вы используете контроллер массива с привязками Cocoa, вам необходимо переопределить метод init(coder:) и инициализировать управляемый контекст там, чтобы выполнить неявную начальную выборку. viewDidLoad слишком поздно.

Рабочий процесс segue такой же, как в iOS. Это еще более удобно, потому что есть свойство presentingViewController, чтобы получить ссылку на родительский контроллер представления.

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

+0

Очень полезно. Так что я переопределяю init в AppDelegate, чтобы передать MOC в SplitViewController, а затем переопределить подготовительную функцию в SplitViewController для передачи MOC в TableViewController? – TDC

+0

Не в AppDelegate, только в контроллерах, которые используют контроллер массива и привязки. Если вы используете singleton, инициализируйте стек в AppDelegate, а затем получите контекст из singleton. – vadian

+0

Я создаю экземпляр класса DataController непосредственно в контроллере, где находится ArrayController. Итак, почему Apple предлагает передать MOC из AppDelegate в контроллеры дочерних элементов Window, а от них до детей? – TDC

0

Это может быть не очень хорошая практика, но, похоже, она работает.

Я сделал свой класс DataController одиночным классом, чтобы убедиться, что существует только один контекст управляемого объекта. В моем TableViewController я создал managedObjectContext свойства следующим образом:

lazy var managedObjectContext = DataController.sharedInstance.managedObjectContext 

В моем контроллере массива я связать управляемый параметр контекста объекта к TableViewController и установить модель Key Путь к self.managedObjectContext.

Можно ли улучшить это?