2014-01-21 5 views
41

Это сложное слово, но у меня есть контроллер вида (vc1), который содержит контейнерный вид (я использую раскадровки). Внутри этого контейнерного представления есть контроллер навигации и контроллер корневого представления (vc2).Как вы можете получить доступ к контроллеру представления, содержащему контейнер?

Изнутри vc2 как я могу получить доступ к vc1?

Или, как мне пройти vc1 в vc2? (имея в виду, что я использую раскадровки).

ответ

49

Вы можете использовать метод prepareForSegue в Vc1 в качестве встроенного segue, когда ContainerViewController превращается в дочерний элемент. вы можете передать себя как obj или сохранить ссылку на ребенка для последующего использования.

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    NSString * segueName = segue.identifier; 
    if ([segueName isEqualToString: @"embedseg"]) { 
     UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController]; 
     Vc2 *detail=[navViewController viewControllers][0]; 
     Vc2.parentController=self; 
    } 
} 

Edit: второстепенный код исправления

+0

@Firula линии 'UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController]; 'не инициализирует ничего своего только указателя на уже инициализированный контроллер. – Bonnie

+1

Итак, во-первых, назовите segue (link) в раскадровке, которая соединяет вид контейнера с его первым контроллером представления. Я назвал свой «toContainer». Затем в контроллере представления, содержащего вид контейнера добавить этот метод - (недействительными) prepareForSegue: (UIStoryboardSegue *) Segue Отправитель: (ID) отправитель { , если ([segue.identifier isEqualToString: @ "toContainer"]) { UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController]; UIViewController * vc2 = [navViewController viewControllers] [0]; } } vc2 был контроллером, на который я хотел получить ссылку. –

+0

примечание: destinationViewController уже был моим контейнером, встроенным в цель UIViewController – BananaAcid

2

Спасибо Бонни, что сказал мне, что делать. Действительно, подготовка к методу segue - это путь.

Я просто уточняю код и шаги здесь.

Во-первых, назовите segue (link) в раскадровке, которая соединяет вид контейнера с его первым контроллером представления. Я назвал свой «toContainer».

Затем в контроллере представления, содержащего вид контейнера добавить этот метод

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([segue.identifier isEqualToString: @"toContainer"]) { 
     UINavigationController *navViewController = (UINavigationController *) [segue destinationViewController]; 
     UIViewController *vc2 = [navViewController viewControllers][0]; 
    } 
} 

Так VC2 был контроллер я хотел бы получить ссылку на.

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

+3

, вы могли бы правильно пометить мой ответ и добавить свои комментарии в комментарии для лучшего уточнения. – Bonnie

+0

Марк, вам нужно правильно пометить ответ Фирулы или Бонни, а затем отредактировать свой вопрос и поместить эту полезную информацию в вопрос. – Fattie

17

Для получения доступа родительского вида контроллера внутри контроллера зрения ребенка необходимо переопределить didMoveToParentViewController:

- (void)didMoveToParentViewController:(UIViewController *)parent { 
    [super didMoveToParentViewController:parent]; 

    //Use parent 
} 

На Xcode Command + Нажмите на этот метод для получения дополнительной информации:

Эти два метода являются общедоступными для контейнерных подклассов для вызова при переходе между дочерними контроллерами . Если они переопределены, переопределения должны обеспечивать вызов супер. Родительский аргумент в оба этих метода равны нулю, когда ребенок удаляется из его родителя; в противном случае он будет равен новому контроллеру родительского представления .

addChildViewController: будет вызывать [child willMoveToParentViewController: self] перед добавлением дочернего элемента . Однако он не будет называть didMoveToParentViewController :. Ожидается, что подкласс контроллера контейнера выполнит этот вызов после завершения перехода к новому дочернему элементу или, в случае без события перехода , сразу после вызова addChildViewController :. Аналогично removeFromParentViewController: не вызывает [self willMoveToParentViewController: nil] перед удалением дочернего элемента . Это также ответственность за контейнерный подкласс.Контейнерные подклассы обычно определяют метод, который переходит к новому дочернему элементу путем первого вызова addChildViewController :, затем выполняется переход , который добавит представление нового дочернего элемента в иерархию представления его родителя и, наконец, вызовет didMoveToParentViewController :. Аналогично, подклассы обычно определяют метод, который удаляет дочерний элемент в обратным образом, сначала вызывая [child willMoveToParentViewController: nil].

1

1) на VC2 выставить свойство для передачи в ссылке на VC1

//VC2.h 
#import "VC1.h" 

@interface VC2 : NSObject 
@property (strong, nonatomic) VC1 *parent; 
@end 

2) на VC1, передать себя в собственность подвергается в VC2 в методе prepareForSegue после идентификатора вы установки вашего SEGUE в к «ToVC2». Затем передайте ссылку следующим образом:

//VC1.m 
@implementation VC1 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
if([segue.identifier isEqualToString:@"ToVC2"]) { 
    VC2 *vc2 = segue.destinationViewController; 
    vc2.parent = self; 
} 
} 
8

Вы можете использовать делегирование, используя тот же метод, который использовался Бонни. Вот как это сделать:

В вашем containerViews ViewController:

class ContainerViewViewController: UIViewController { 
    //viewDidLoad and other methods 

    var delegate: ContainerViewControllerProtocol? 

    @IBAction func someButtonTouched(sender: AnyObject) { 
    self.delegate?.someDelegateMethod() //call this anywhere 
    } 

} 

protocol ContainerViewControllerProtocol { 
    func someDelegateMethod() 
} 

В вашей материнской ViewController:

class ParentViewController: UIViewController, ContainerViewControllerProtocol { 
    //viewDidLoad and other methods 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     if segue.identifier == "filterEmbedSegue" { 
      let containerViewViewController = segue.destinationViewController as ContainerViewViewController 

      containerViewViewController.delegate = self 
     } 
    } 

    func someDelegateMethod() { 
     //do your thing 
    } 
} 
8

Использование свойств parentViewController в self.parentViewController

+7

В моем случае это не работало как self.parentViewController было нулевым. Я добавил контейнерView в раскадровку, а затем назначил связанный класс контроллера классов своим конкретным подклассом. Я ожидал, что parentViewController будет установлен в VC, который содержит представление контейнера, но это не устанавливается автоматически. Мне пришлось использовать -prepareForSegue решение выше –

+0

свойство «я».родитель "в быстрой 3 –

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