2014-11-05 2 views
8

У меня есть приложение Core Data на основе документов Mac, в котором используются раскадровки. Раскадровка имеет следующую структуру:Использование NSArrayController в нескольких сценариях раскадровки

Window Controller 
    Split View Controller 
     Table View Controller 
     Text View Controller 

модель My основных данных содержит Глава объект, который содержит два атрибута: заголовок и содержимое. Я хочу, чтобы в представлении таблицы отображалось название каждой главы. Текстовое представление отображает содержимое выбранной главы.

Если я использовал xib-файл, я бы добавил контроллер массива в файл xib. Я бы привязал контроллер массива к владельцу файла для доступа к подклассу NSPsistentDocument. Я бы привязал представление таблицы к свойству allocObjects контроллера массива и привязал текстовое представление к выбору контроллера массива.

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

Как добавить контроллер массива в Interface Builder, чтобы как контроллер представления таблиц, так и контроллер текстового вида могли получить к нему доступ и привязаться к нему?

+0

Просто вставить его в приложении делегате как свойство ... (шучу, в основном.) Но что keypaths существует взгляды родительских в раскадровки OSX? – stevesliva

+1

NSViewController имеет свойство parentViewController. Но если я добавлю контроллер массива в контроллер разделенного представления и привяжу привязку столбца таблицы представления таблицы к контроллеру табличного представления, используя путь ключа модели parentViewController.arrayController.arrangedObjects, приложение выйдет из строя, сказав, что класс не соответствует KVC для key arrayController. Я добавил выход для контроллера массива в мой подкласс класса split view и подключил выход к контроллеру массива I, созданному в IB, и произошел тот же самый сбой. –

+0

Я читал это снова ... Возможно, переопределите getoverController родителя, чтобы вернуть конкретный подкласс, у которого есть свойство arrayController? Впрочем, это уродливо. – stevesliva

ответ

14

Ключом к выполнению этой работы является наличие экземпляра NSArrayController в каждом из ваших подклассов NSViewController и их связывание через центральный источник данных (скорее всего, ваш подкласс NSDocument). Затем вы можете установить этот источник данных в качестве своих подклассов NSViewControllerrepresentedObject, передав их вниз по вашим нисходящим контроллерам . Вот пример раскадровки приложения с NSWindowController который имеет контроллер представления контента, который является NSSplitViewController с двумя контроллерами зрения ребенка (Master/установки Detail):

class Document: NSDocument { 

    var dataSource: DataSource? = DataSource() 

    ... 
} 

class DataSource: NSObject, NSCoding { 

    var items: [Item] = [] 
    var selectionIndexes: NSIndexSet = NSIndexSet() 

    ... 
} 

class WindowController: NSWindowController { 

    override var document: AnyObject? { 
     didSet { 
      if let document = self.document as? Document { 
       self.contentViewController?.representedObject = document 
      } 
     } 
    } 

} 

class SplitViewController: NSSplitViewController { 

    override var representedObject: AnyObject? { 
     didSet { 
      for viewController in self.childViewControllers as! [NSViewController] { 
       viewController.representedObject = representedObject 
      } 
     } 
    } 
} 

Хитрость заключается в том, чтобы связать representedObject друг вашего нисходящего контроллера просмотра NSArrayController в раскадровке. Вы должны привязать НЕ ТОЛЬКО contentArray НО ТАКЖЕ selectionIndexes.

Результатом является то, что на обоих selectionIndexes нисходящих NSArrayController с сохраняются в синхронизации, потому что они связаны через центральный источник данных (DataSource подкласса в приведенном выше примере).

Для того, чтобы это все яснее я создал пример проект, который демонстрирует это здесь: https://github.com/acwright/StoryboardBindingsExample

+0

Впечатляет.Я загрузил ваш пример, и он работает. Хотел бы я получить этот ответ несколько месяцев назад. Я отказался от использования привязок для моего текущего проекта, и я не вернусь назад, но я буду учитывать этот ответ для будущих проектов, которые используют раскадровки. –

+0

Спасибо! Я собирался отказаться от привязок для проекта, который я начинал, но я чувствовал, что решение должно быть возможным! Затем мне пришло в голову, что на самом деле это просто вопрос синхронизации выборов! :) –

+0

У вас есть это для работы с Core Data? У меня была схожая идея с тем, что вы сделали, но пока я могу получить индекс выбора и доказать, что он обновляется с одной сцены, я всегда получаю пустой контроллер массива во второй сцене. – LighteningKid

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