it-swarm.com.ru

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

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

Сценарий:

example

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

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

186
Adam Waite

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

- (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's subviews here...
   }
}
348
Peter E

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

50
rdelmar

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

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

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
    }
}
23
Sruit A.Suk

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

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

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

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

15
SimplGy

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

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

Это только повторяет список детей, пока не достигнет первого совпадения.

9
Robin Daugherty

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

8
Gautam Jain

Если кто-то ищет 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")
}
1
Marco Leong

С дженериком вы можете делать некоторые приятные вещи. Вот расширение для Array:

extension Array {
    func firstMatchingType<Type>() -> Type? {
        return first(where: { $0 is Type }) as? Type
    }
}

Затем вы можете сделать это в вашем viewController:

var viewControllerInContainer: YourViewControllerClass? {
    return childViewControllers.firstMatchingType()!
}
1
Sunkas

Есть другой способ, используя оператор переключения 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
  }
}
1
Joanna Carter

Я использую код как:

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

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

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