Как встраивать зависимости в контроллер представления iOS?

Мои диспетчеры представлений должны отправлять сообщения нескольким объектам модели. Как получить ссылки на эти объекты модели внутри контроллера представления?

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

Я не могу использовать инсталляцию конструктора, так как среда выполнения выбирает метод init, который используется для создания контроллера представления.

Я не могу использовать "setter injection", как ни в какой точке (что мне известно) у меня есть ссылка на недавно построенный контроллер представления и ссылки на объекты модели "singleton".

Я не хочу превращать объекты модели в правильные синглтоны и вызывать на них статический метод из контроллеров представления для извлечения экземпляра singleton, поскольку это проблема проверки. (Наличие объектов модели как свойств в AppDelegate по существу совпадает с этим.)

Я использую iOS 6 с раскадровки.

Ответ 1

Я только что рассмотрел ту же проблему. Поскольку я использую раскадровку, я не создаю экземпляр UIViewControllers, поэтому я не могу использовать "инъекцию конструктора". Я должен уйти в отставку, используя инъекцию сеттера.

Мой корень приложения - UITabViewController. Пусть говорят, что он имеет два UINavigationController s, имеющих первый a AControllerView и второй BControllerView. В AppDelegate.applicationDidFinishLaunchingWithOptions вы можете получить корневой контроллер таким образом:

UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController;

Затем вы можете выполнять итерацию через контроллеры:

NSArray* viewControllers = [tabBarController viewControllers];
for (UIViewController *viewController in viewControllers) {
    UINavigationController *navigationController = (UINavigationController*) viewController;
    UIViewController *viewController = navigationController.topViewController;
    if ([viewController isKindOfClass: [AControllerView class]]) {
        AControllerView *a = (AControllerView*) viewController;
        // Inject your stuff
    }
    if ([viewController isKindOfClass: [BControllerView class]]) {
        BControllerView *b = (BControllerView*) viewController;
        // Inject your stuff
    }
}

Надеюсь, это поможет.

Ответ 2

Почему бы не использовать NSNotificationCenter?

Объект NSNotificationCenter (или просто центр уведомлений) предоставляет механизм для передачи информации внутри программы. Объект NSNotificationCenter является, по существу, таблицей отправки уведомлений.

Вы можете добавить наблюдателя уведомлений как в одноэлементном, так и в обычном, а когда вам нужно отправлять сообщения, просто отправьте правильное уведомление. Наблюдатели теперь будут управлять действием.

Подробнее о NSNotificationCenter.

Ответ 3

Разве это не связано с получением ссылки на объект контроллера представления? Если вы используете раскадровку, то окна rootViewController или используемые segues предоставят вам правильный объект контроллера.

то есть: Экземпляр контроллера просмотра при запуске приложения

self.window.rootViewController

Когда вы переходите к переходу между сценами (контроллерами просмотра):

[segue destinationViewController] или [segue sourceViewController]

Если вы используете xibs, вы можете даже использовать внешний объект (прокси-объект) из конструктора интерфейса для поставки объекта модели. Единственное, что вам нужно, - это взять экземпляр nib в свои руки.

Ответ 4

В идеале в какой-то момент сторонним разработчикам будет разрешено использовать собственные конструкторы/инициализаторы даже при использовании раскадровки.

До тех пор вы могли бы использовать инъекцию setter/property и шаблон посредника, тем более, что вы привыкли к лучшим практикам и свободному соединению.

Я написал об этом здесь: http://cocoapatterns.com/passing-data-between-view-controllers/