в iOS6 Я заметил новый Container View, но не совсем уверен, как получить доступ к нему с помощью содержащего представления.
Сценарий:
Я хочу получить доступ к меткам в контроллере представления предупреждений с контроллера представления, в котором находится представление контейнера.
Есть ли между ними переход, могу ли я использовать это?
Да, вы можете использовать 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...
}
}
Вы можете сделать это просто с помощью self.childViewControllers.lastObject
(если у вас есть только один ребенок, в противном случае используйте objectAtIndex:
).
для быстрого программирования
вы можете написать вот так
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
}
}
Подход prepareForSegue
работает, но он полагается на магическую строку идентификатора segue. Может быть, лучший способ.
Если вы знаете класс VC, который вам нужен, вы можете сделать это очень аккуратно с вычисленным свойством:
var camperVan: CamperVanViewController? {
return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
// This works because `flatMap` removes nils
}
Это зависит от childViewControllers
. Хотя я согласен, это может быть хрупким, чтобы полагаться на первое, назвав класс, который вы ищете, это кажется довольно прочным.
return childViewControllers.filter { $0 is CamperVanViewController }.first
в один return childViewControllers.filter { $0 is CamperVanViewController }.first
childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
я думаю, что это немного лучше, так как он отбрасывает и избавляется от любых нулей.
self.childViewControllers
более уместен, когда вам нужен контроль над родителем. Например, если дочерний контроллер является табличным представлением, и вы хотите его принудительно перезагрузить или изменить свойство с помощью нажатия кнопки или любого другого события в Parent View Controller, вы можете сделать это, обратившись к экземпляру ChildViewController, а не через prepareForSegue. Оба имеют свои приложения по-разному.
Обновленный ответ для Swift 3, используя вычисленное свойство:
var jobSummaryViewController: JobSummaryViewController {
get {
let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController })
return ctrl as! JobSummaryViewController
}
}
Это только повторяет список дочерних элементов, пока не достигнет первого совпадения.
Существует другой способ использования оператора переключения 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
}
}
Если кто-то ищет 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")
}
Я использую Code like:
- (IBAction)showCartItems:(id)sender{
ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
[self addChildViewController:listOfItemsVC];
}
вы можете написать вот так
- (IBAction)showDetail:(UIButton *)sender {
DetailViewController *detailVc = [self.childViewControllers firstObject];
detailVc.lable.text = sender.titleLabel.text;
}
}