Ответ 1
Когда у вас есть дочерние представления, у которых есть свои собственные контроллеры представлений, вы должны следовать шаблону настраиваемого контроллера контейнера. Подробнее см. Создание пользовательских контроллеров Просмотр контейнеров.
Предполагая, что вы выполнили шаблон пользовательского контейнера, если вы хотите изменить контроллер дочернего представления (и связанный с ним просмотр) для "представления содержимого", вы сделали бы это программно с помощью чего-то вроде:
UIViewController *newController = ... // instantiate new controller however you want
UIViewController *oldController = ... // grab the existing controller for the current "content view"; perhaps you maintain this in your own ivar; perhaps you just look this up in self.childViewControllers
newController.view.frame = oldController.view.frame;
[oldController willMoveToParentViewController:nil];
[self addChildViewController:newController]; // incidentally, this does the `willMoveToParentViewController` for the new controller for you
[self transitionFromViewController:oldController
toViewController:newController
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
// no further animations required
}
completion:^(BOOL finished) {
[oldController removeFromParentViewController]; // incidentally, this does the `didMoveToParentViewController` for the old controller for you
[newController didMoveToParentViewController:self];
}];
Когда вы это делаете, нет необходимости в каком-либо интерфейсе делегат-протокол с контроллером представления контента (кроме того, что iOS уже предоставляет с помощью Manage Child View Controllers в пользовательских контейнерах).
Кстати, это предполагает, что начальный дочерний контроллер, связанный с этим представлением содержимого, был добавлен так:
UIViewController *childController = ... // instantiate the content view controller any way you want
[self addChildViewController:childController];
childController.view.frame = ... // set the frame any way you want
[self.view addSubview:childController.view];
[childController didMoveToParentViewController:self];
Если вы хотите, чтобы дочерний контроллер передавал родительскому элементу изменения контроллера, связанного с представлением содержимого, вы должны:
-
Определите протокол для этого:
@protocol ContainerParent <NSObject> - (void)changeContentTo:(UIViewController *)controller; @end
-
Определите родительский контроллер для соответствия этому протоколу, например:
#import <UIKit/UIKit.h> #import "ContainerParent.h" @interface ViewController : UIViewController <ContainerParent> @end
-
Внедрите метод
changeContentTo
в родительском контроллере (как описано выше):- (void)changeContentTo:(UIViewController *)controller { UIViewController *newController = controller; UIViewController *oldController = ... // grab reference of current child from `self.childViewControllers or from some property where you stored it newController.view.frame = oldController.view.frame; [oldController willMoveToParentViewController:nil]; [self addChildViewController:newController]; [self transitionFromViewController:oldController toViewController:newController duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ // no further animations required } completion:^(BOOL finished) { [oldController removeFromParentViewController]; [newController didMoveToParentViewController:self]; }]; }
-
Теперь дочерние контроллеры могут использовать этот протокол в отношении свойства
self.parentViewController
, которое iOS предоставляет вам:- (IBAction)didTouchUpInsideButton:(id)sender { id <ContainerParent> parentViewController = (id)self.parentViewController; NSAssert([parentViewController respondsToSelector:@selector(changeContentTo:)], @"Parent must conform to ContainerParent protocol"); UIViewController *newChild = ... // instantiate the new child controller any way you want [parentViewController changeContentTo:newChild]; }