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

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

Сценарий:

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

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

 Fattie12 дек. 2016 г., 21:50
полностью объяснено здесь, для современных контейнеров:stackoverflow.com/a/23403979/294884

Ответы на вопрос(11)

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

 Lay González20 июн. 2014 г., 19:54
@Fydo, и в чем проблема с обработкой всех контейнеров наподготовиться к переходу?
 Mazyod04 мая 2016 г., 17:02
Это мой обычный подход, но теперь он дает сбой, так как я получаю доступ кchildViewControllers "слишком рано
 Tom Andersen15 апр. 2015 г., 22:23
Что если (ужас!) Вы решите переключиться с раскадровки или не использовать seques и т. Д. Затем вы должны выкопать код, внести изменения и т. Д.
 Fydo04 июн. 2014 г., 14:05
@RaphaelOliveira, не обязательно. Если у вас есть несколько дочерних контроллеров в одном представлении, ЭТО будет предпочтительным подходом. Это позволяет координировать несколько контейнеров одновременно. prepareForSegue имеет ссылку только на один экземпляр дочернего контроллера это 'действует на.
Решение Вопроса

вы можете использовать segue для получения доступа к дочернему контроллеру представления (а также к его представлению и подпредставлениям). йте segue идентификатор (такой как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...
   }
}
 Adam Waite08 нояб. 2012 г., 00:09
мы неT Seguing? я что-то здесь упускаю ...?
 Peter E08 нояб. 2012 г., 14:14
точнее, он вызывается перед viewDidLoad. К моменту достижения viewDidLoad родитель и потомок уже подключены, и [self childViewControllers] в родительском элементе вернет массив всех дочерних контроллеров (см. Rdelmar 'ответ ниже).
 Adam Waite08 нояб. 2012 г., 12:23
Ах да, даконтроллер второго вида сделан дочерним по отношению к контроллеру первого вида когда вид загружается? Это имеет больше смысла, спасибо. Я'Я не с моим проектом сейчас, но буду проверять позже
 Sarim Sidd26 апр. 2013 г., 09:07
Можете ли вы объяснить эту строку .. AlertView * alertView = childViewController.view; Что такое "AlertView» ссылаясь на? это родительский контроллер? Извините, я новичок в iOS
 Fattie25 мая 2017 г., 14:22
странная терминологияпереход» здесь объясняется:stackoverflow.com/a/23403979/294884
 Hamal00028 мая 2013 г., 19:40
Приведение к AlertViewController не требуется, поскольку свойство destinationViewController возвращает идентификатор.
 AlwaysLearning12 нояб. 2012 г., 01:44
Я бы добавил одно предостережение к предлагаемому решению: будьте очень осторожны при доступе к (дочернему) контроллеру целевого представления 'Свойство view: в некоторых случаях это будет вызывать его viewDidLoad тут же. Я бы порекомендовал заранее настроить любые необходимые данные segue, чтобы viewDidLoad мог безопасно запускаться.
 Peter E08 нояб. 2012 г., 02:46
да, есть ситуация внедрения, которая возникает, когда второй контроллер представления становится дочерним по отношению к первому контроллеру представления. prepareForSegue: вызывается как раз перед тем, как это произойдет. Вы можете использовать эту возможность для передачи данных ребенку или для сохранения ссылки на ребенка для последующего использования. смотрите такжеdeveloper.apple.com/library/ios/#documentation/uikit/reference/...
 memmons23 сент. 2014 г., 16:11
Вместо того чтобы создавать произвольные строки для сравнения при использовании prepareForSequeisKindOfClass вместо.
 clearlight02 февр. 2015 г., 15:52
Но @ MichaelG.Emmons - именование сегментов в раскадровке - это S.O.P. Что, если prepareForSegue () имеет другие типы сегментов, где тип контроллера назначения был одинаковым, но, возможно, разными экземплярами? В этом случае выЯ хотел бы знать, что было, и segue.id был бы способ сделать это. Может быть, это нев жизни это не случается, но все же .. В любом случае, проверка типа в Swift: если segue.destinationViewController равен <containingViewControllerClass> {self.containerController = segue.destinationViewControler as <Содержит ViewContollerClass}

ие для Array:

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

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

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

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")
}

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

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

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

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

 Adam Waite05 мая 2016 г., 15:29
хороший, выглядит хорошо
 Alexander06 сент. 2017 г., 22:11
дон»Фильтровать только для первого элемента. просто используйте.first(where:)childViewControllers.first(where: { $0 is CamperVanViewController })
 Adam Waite04 мая 2016 г., 12:46
return childViewControllers.filter { $0 is CamperVanViewController }.first в один лайнер
 SimplGy04 мая 2016 г., 19:14
мы сделалиchildViewControllers.flatMap({ $0 as? CamperVanViewController }).first что я думаю, немного лучше, так как он бросает и избавляется от любых нулей.
 Gabox11 июл. 2016 г., 06:39
Это действительно хорошее решение, если вы хотите получить доступ к этому контроллеру более одного раза
 Fattie25 мая 2017 г., 14:23
это безнадежно - тамНет особой причины, по которой у вас может быть только один из этого класса. тот'точно, почему существуют идентификаторы. просто следуйте стандартной формуле ...stackoverflow.com/a/23403979/294884

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

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

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

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

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

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

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
    }
}
 the Reverend04 февр. 2016 г., 23:07
Какая польза от знака вопроса после segueName в операторе if? "если segueName? "

оллера представления:

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

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

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

Ваш ответ на вопрос