2014-12-30 3 views
18

Я в настоящее время сражаюсь с NSDocument в документе, основанном на каскаде на основе раскадровки (Цель C). Может ли кто-нибудь сказать мне, как я могу получить доступ к документу в подклассе NSViewController?Mac App Storyboard - доступ к документу в NSViewController

Я попытался открыть его следующим образом - но документ не является:

[self.view.window.windowController document]; 

Спасибо за вашу помощь!

С наилучшими пожеланиями Мартин

+0

как вы реализуете NS-Document® '-makeWindowControllers'? call '-addWindowController:' как шаблон по умолчанию? – bluedome

+0

да реализовано как follwos: - (void) makeWindowControllers { // Переопределить, чтобы вернуть имя файла раскадровки документа. [self addWindowController: [[NSStoryboard storyboardWithName: @ "Main" bundle: nil] instantiateControllerWithIdentifier: @ "Контроллер окна документа"]]; } – Martin

+0

где вы помещаете код '[self.view.window.windowController document]' в подкласс NSViewController? – bluedome

ответ

16

Я просто борьба с этим сам. Я начал со стандартного шаблона Yosemite и пытался использовать [self.view.window.windowController document] в -viewDidLoad. В этот момент self.view.window - nil, так что нет никакого способа добраться до document.

Трюк должен подождать до -viewWillAppear. К тому времени, когда он называется, заполняется self.view.window и доступен document.

Последовательность: -makeWindowControllers вызывает -self addWindowController: с раскадровкой - instantiateControllerWithIdentifier: результат. -addWindowController: вызывает звонок до -viewDidLoad VC перед возвратом. Затем, наконец, вызывается -viewWillAppear (и доступен document).

+1

Это работает, и теперь я устанавливаю 'visibleObject' контроллера представления в методе' viewWillAppear' для документа окна контроллера. Но мне интересно, действительно ли так оно и должно быть. Работает, но чувствует себя взломанным. – Pascal

+1

Добавление примечания для следующего парня: если у вас есть NSTableView в окне вашего документа, он вызовет его методы делегирования на вашем viewController до того, как будет установлен документ, что затрудняет выполнение таких действий, как возврат количества строк. Одним из решений является установка 'viewWillAppear' с' myTableView.reloadData', чтобы заставить его вызывать методы после того, как документ действителен. –

1

Я знаю, что исходный вопрос был для Objective-C, но для других, использующих Swift, могут помочь протоколы. Основная концепция может быть применена и в Objective-C.

Вместо того, уходящие к контроллеру окна, вы можете использовать инъекции зависимостей:

1) Создать document свойства на контроллере окна и любое представление контроллерах, которые должны получить доступ к документу (или использовать representedObject свойства, уже существует). Чтобы сделать это проще, вы можете использовать протокол для определения свойства документа или для присвоения свойства representedObject вашему типу документа, если вы идете по этому маршруту. Сделать все контроллеры представлений, которым необходимо получить доступ к документу, принять этот протокол.

protocol DocumentAccessing { 
    var document: MyDocument? { get set } // could also use an implicitly unwrapped optional if the document is required to be set for the app to function 
} 

2) В makeWindowControllers() методы вашего документа подкласса, после создания контроллера окна, установите его свойство документа самостоятельно (как это документ).

- (void)makeWindowControllers { 
    MyWindowController *windowController = MyWindowController() 
    windowController.document = self; 
    [self addWindowController:windowController]; 
} 

3) Внутри вашего окно контроллера подкласса, после создания экземпляра контроллеров просмотра, установите свойство документа контроллера представления в свойство документа контроллера окна.

4) Теперь, когда ваш контроллер просмотра загружен, его свойство документа должно быть заполнено.

1

Это не относится к вопросу напрямую. Но Q & Ниже приведена ссылка на то, как получить доступ к модели данных в документе из объектов NSControl с помощью привязок, используя подготовленный объект NSViewController.

https://developer.apple.com/library/content/qa/qa1871/_index.html

Я установил representedObject для NSViewController в документе.м следующим образом:

- (void)makeWindowControllers { 
NSWindowController* wc = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"]; 
NSViewController* vc = wc.contentViewController; 
vc.representedObject = self.model; 

[self addWindowController:wc]; 

}

Теперь representedObject моей ViewController установлен в модели. Предполагая, что моя модель имеет свойство text, я могу связать любой NSControl с этим свойством с помощью ViewController с помощью keyPath: self.representedObject.text