Ссылка IBOutlet на встроенный контроллер представления

StackOverflow https://stackoverflow.com//questions/12676660

  •  12-12-2019
  •  | 
  •  

Вопрос

У меня есть сложное представление iPad, которым я управляю с помощью нескольких контроллеров представления.Раньше (до iOS6/XCode 4.5) я делал это, выделяя контроллеры представлений в коде и подключая к ним различные представления через ссылки на главное представление.

Я хотел бы использовать новые представления контейнера для встраивания контроллеров представлений в файл раскадровки.Кажется, я не могу сделать ссылку IBOutlet на встроенный контроллер представления на главный контроллер.

Можно ли сделать это?Или получить встроенный контроллер через тег или что-то в коде?

Этот вопрос КОНКРЕТНО касается использования представлений контейнера.

Это было полезно?

Решение

Я не уверен, что вы подразумеваете под «Получение встроенного контроллера».Когда вы хотите использовать контроллер, вы используете метод Uistoryboard InstantiateViewControllerWithdiTifier:, используя идентификатор, который вы даете контроллеру в IB.Вы также можете использовать SpecialsegeWithdentifier: Sender: Method (который также создал контроллер представления).Вы должны проверить «Использование контроллеров просмотра в вашем приложении» в разделе Apple.Он также имеет отношение к тому факту, что контроллеры дочернего представления создаются одновременно, что и контроллер контейнера.

После редактирования: если вы встраиваете вид контейнера в другой контроллер представления, контроллер встроенного представления может быть указан из содержащего контроллер с Self.childViewControllers (который будет массивом, поэтому, если есть только один, вы можете получить егос lastObject).

Другие советы

Другой вариант для некоторых случаев — захват встроенного контроллера с помощью -prepareForSegue:sender:.

Например, если у меня есть UINavigationController встроенный в CustomContainerViewController, я могу назвать переход к вставке embedContentStack в раскадровке и зафиксируйте его в CustomContainerViewController с помощью

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"embedContentStack"]) {
        // can't assign the view controller from an embed segue via the storyboard, so capture here
        _contentStack = (UINavigationController *)segue.destinationViewController;
    }
}

Примечание предостережения

Прежде чем приступить к ответу на этот вопрос, вы можете подумать, действительно ли встроенные элементы должны быть контроллерами представления.

Например, если вы встраиваете UICollectionViewController подкласс, не могли бы вы вместо этого встроить UICollectionView подкласс?Или, еще лучше, не могли бы вы встроить UIView подкласс, который скрывает UICollectionView за простой ViewModel?

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

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

Фон

Я использую подход, заключающийся в выборе перехода вставки в prepare(for segue:, sender:) как было предложено Игривый Компьютерщик здесь.

Я хотел показать Swift, который я использую для этого, поскольку он кажется довольно аккуратным…

class EditionLandingViewController: UIViewController {
    fileprivate var titlesView: SectionTitlesViewController!
    fileprivate var sectionsView: SectionsViewController!
}

//MARK:-

extension EditionLandingViewController {
    private enum SegueId: String {
        case embedTitles
        case embedSections
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        guard
            let segueRawId = segue.identifier,
            let segueId = SegueId(rawValue: segueRawId)
            else { return }

        switch segueId {
        case .embedTitles:
            self.titlesView = segue.destination as! SectionTitlesViewController

        case .embedSections:
            self.sectionsView = segue.destination as! SectionsViewController
        }
    }
}

Обсуждение

Я решил называть переходы как методы действий.

Используя enum Случаи для идентификаторов перехода означают, что на вашей стороне есть компилятор и инструменты, поэтому гораздо сложнее ошибиться в имени перехода.

Сохранение идентификаторов перехода в private enum в рамках extension в данном случае область видимости кажется подходящей, поскольку эти переходы больше нигде не нужны (они не могут быть performизд, например).

Я использую неявно развернутые типы для встроенных контроллеров представления, потому что (во всяком случае, в моем случае) их отсутствие является логической ошибкой.

Точно так же я также рад принудительно привести типы контроллеров представления назначения.Опять же, было бы логической ошибкой, если бы эти типы не были одинаковыми.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top