Изнутри контроллера представления в представлении контейнера, как вы получаете доступ к контроллеру представления, содержащему контейнер?

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

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

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

Ответ 1

Вы можете использовать метод 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;
    }
}

Изменить: незначительное исправление кода

Ответ 2

Чтобы получить доступ к контроллеру родительского представления из вашего контроллера дочернего представления, вы должны переопределить didMoveToParentViewController:

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

    //Use parent
}

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

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

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

Ответ 3

Используйте свойство parentViewController как self.parentViewController

Ответ 4

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

В вашем контейнере 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
    }
}

Ответ 5

Спасибо, Бонни, что рассказала мне, что делать. Действительно, подготовка к методу 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 не был навигационным контроллером.

Ответ 6

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;
}
}