Доступ к контроллеру просмотра контейнера из родительского iOS

в iOS6 Я заметил новый Container View, но не совсем уверен, как получить доступ к нему с помощью содержащего представления.

Сценарий:

example

Я хочу получить доступ к меткам в контроллере представления предупреждений с контроллера представления, в котором находится представление контейнера.

Есть ли между ними переход, могу ли я использовать это?

Ответ 1

Да, вы можете использовать segue, чтобы получить доступ к контроллеру дочернего представления (и его представлению и представлениям). Дайте segue идентификатор (например, alertview_embed), используя инспектор атрибутов в Storyboard. Затем, если родительский контроллер представления (тот, в котором находится контейнер), реализует такой метод:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
   NSString * segueName = segue.identifier;
   if ([segueName isEqualToString: @"alertview_embed"]) {
       AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController];
       AlertView * alertView = childViewController.view;
       // do something with the AlertView subviews here...
   }
}

Ответ 2

Вы можете сделать это просто с помощью self.childViewControllers.lastObject (если у вас есть только один ребенок, в противном случае используйте objectAtIndex:).

Ответ 3

для быстрого программирования

вы можете написать вот так

var containerViewController: ExampleViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // you can set this name in 'segue.embed' in storyboard
    if segue.identifier == "checkinPopupIdentifierInStoryBoard" {
        let connectContainerViewController = segue.destinationViewController as ExampleViewController
        containerViewController = connectContainerViewController
    }
}

Ответ 4

Подход prepareForSegue работает, но он полагается на магическую строку идентификатора segue. Может быть, лучший способ.

Если вы знаете класс VC, который вам нужен, вы можете сделать это очень аккуратно с вычисленным свойством:

var camperVan: CamperVanViewController? {
  return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
  // This works because `flatMap` removes nils
}

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

Ответ 5

self.childViewControllers более уместен, когда вам нужен контроль над родителем. Например, если дочерний контроллер является табличным представлением, и вы хотите его принудительно перезагрузить или изменить свойство с помощью нажатия кнопки или любого другого события в Parent View Controller, вы можете сделать это, обратившись к экземпляру ChildViewController, а не через prepareForSegue. Оба имеют свои приложения по-разному.

Ответ 6

Обновленный ответ для Swift 3, используя вычисленное свойство:

var jobSummaryViewController: JobSummaryViewController {
    get {
        let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController })
        return ctrl as! JobSummaryViewController
    }
}

Это только повторяет список дочерних элементов, пока не достигнет первого совпадения.

Ответ 7

Я использую Code like:

- (IBAction)showCartItems:(id)sender{ 
  ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
  [self addChildViewController:listOfItemsVC];
 }

Ответ 8

Если кто-то ищет Swift 3.0,

viewController1, viewController2 и т.д. тогда будет доступно.

let viewController1 : OneViewController!
let viewController2 : TwoViewController!

// Safety handling of optional String
if let identifier: String = segue.identifier {

    switch identifier {

    case "segueName1":
        viewController1 = segue.destination as! OneViewController
        break

    case "segueName2":
        viewController2 = segue.destination as! TwoViewController
        break

    // ... More cases can be inserted here ...

    default:
        // A new segue is added in the storyboard but not yet including in this switch
        print("A case missing for segue identifier: \(identifier)")
        break
    }

} else {
    // Either the segue or the identifier is inaccessible 
    print("WARNING: identifier in segue is not accessible")
}

Ответ 9

Существует другой способ использования оператора переключения Swift для типа контроллера вида:

override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
  switch segue.destination
  {
    case let aViewController as AViewController:
      self.aViewController = aViewController
    case let bViewController as BViewController:
      self.bViewController = bViewController
    default:
      return
  }
}

Ответ 10

вы можете написать вот так

- (IBAction)showDetail:(UIButton *)sender {  
            DetailViewController *detailVc = [self.childViewControllers firstObject];  
        detailVc.lable.text = sender.titleLabel.text;  
    }  
}