2012-05-30 5 views
0

У меня есть контроллер контейнера с 3 дочерними подклассами UIViewController (добавлен с addChildViewController). Я хочу, чтобы один из контроллеров моего дочернего представления делал что-то, когда что-то было удалено из моего контроллера представления контейнера на него. Мне трудно понять, как это сообщение должно произойти. Если я попытаюсь сделать делегат, я получаю сообщение об ошибке в контроллере моего дочернего представления, потому что оба подкласса будут импортировать друг друга.Связь контроллера контроллера контейнера с childViewControllers

ответ

5

Похоже, что у вас возникла проблема компиляция вашего приложения из-за взаимных файлов .h importing друг друга, не так ли?

Edit: при чтении свой вопрос еще раз, я не 100% ясно, на какой вид контроллер должен вызывать какие другие один. Если я смешал роли родительского и дочернего контроллера вида в моем решении, просто переключи их . Методы ниже позволяют общаться между любыми двумя контроллерами зрения (родителем и ребенком, братом или сестрой и братом и т.д.)

Там есть несколько способов справиться с этим. Если Вы хотите разместиться с delegate шаблон, можно просто переписать заголовок, чтобы избежать #import в одном из заголовочных файлов:

ParentViewController.h:

#import "ChildViewController.h" 

@interface ParentViewController: UIViewController { 
@private 
    ChildViewController* childVc; 
} 

- (void) doSomething; 

ChildViewController.h

@class ParentViewController; // NOT #import! 

@interface ChildViewController: UIViewController { 
@private 
    ParentViewController* parentVc; 
} 

ChildViewController.m

#import "ParentViewController.h" 

Это должно избегать циклической зависимости, которая не позволяет компиляции вашего приложения.

Теперь, хотя вышеупомянутые работы, я могу выбрать другое решение, ради чистоты. Используйте . Родитель может реализовать протокол, а затем ребенок должен только есть делегат, который реализует протокол:

#import "MyProtocol.h" 

@interface ParentViewController: UIViewController<MyProtocol> { 

} 

- (void) doSomething; 

В MyProtocol.h:

@protocol MyProtocol 
- (void) doSomething; 
@end 

Тогда в ChildViewController.h

#import "MyProtocol.h" 

@interface ChildViewController: UIViewController { 
@private 
    id<MyProtocol> delegate; 
} 

@property (nonatomic, assign) id<MyProtocol> delegate; 

И в ChildViewController.m:

[delegate doSomething]; 

Или вы могли бы избежать использования делегатов в целом и communicate between the controllers using NSNotificationCenter, что немного их откупоривает и позволяет избежать кругооборота вашего компилятора (двунаправленная зависимость).

Here are the Apple docs on NSNotificationCenter

+0

NSNotifications работает отлично! Благодаря! –

+2

Я согласен с использованием протоколов здесь. Ребенок не должен иметь ссылку на родителя. Однако это не подходящее место для использования NSNotificationCenter. Вы использовали бы это для передачи сообщения нескольким объектам, а не только родительскому объекту в контейнере. Делегирование - правильное решение. – smileBot

2

не могли бы вы просто пойти:

MyChildViewController *myChildViewController = (MyChildViewController *)[self.childViewControllers objectAtIndex:0]; 
[myChildViewController doWhatever]; 

? Это должно дать вам сообщение о контроллере дочернего представления в первом индексе массива childViewControllers (который является свойством в UIViewController).

+0

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

+0

Я не могу говорить с лучшей практикой. – geraldWilliam

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