Значение делегата равно нулю при использовании представлений контейнера

#ios #swift #delegates #containers #container-view

#iOS #swift #делегаты #контейнеры #container-view

Вопрос:

У меня есть 2 представления контейнера, в которые встроены UITableViewController (sideMenuVC) и UICollectionViewController (centerVC) соответственно, а мой CollectionVC находится внутри самого контроллера навигации. Я поместил эти два представления контейнера внутри третьего VC, который является rootVC. Теперь я пытаюсь отобразить содержимое в моем centerVC на основе строки, выбранной в sideMenuVC, и я использую делегаты, однако значение делегата равно нулю, когда я пытаюсь вызвать его от отправителя. Я попытался установить делегат как слабый, а также установить делегат в awakeFromNib вместо viewDidLoad, я также попытался установить делегата из разных виртуальных машин.

Вот мой протокол:

 import Foundation
import Photos

protocol sideMenuDelegate {
    func handleRowSelection(title: String, fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?)
}
  

и вот как я устанавливаю делегат внутри третьего VC, который содержит оба представления контейнера:

 let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
sideMenuVC = storyboard.instantiateViewController(withIdentifier: "sideVC") as? SideMenuViewController
centerVC = storyboard.instantiateViewController(withIdentifier: "centerVC") as? centerViewController
sideMenuVC?.delegate = centerVC
  

Я также попытался установить его в своем centerVC следующим образом:

 let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
sideMenuVC = storyboard.instantiateViewController(withIdentifier: "sideVC") as? SideMenuViewController
sideMenuVC?.delegate = self
  

и, наконец, это реализация функции делегирования:

 extension centerViewController: sideMenuDelegate {
    func handleRowSelection(title: String, fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?) {
        pageTitle = title
        inFetchResult = fetchResult
        inAssetCollection = assetCollection
    }  
}
  

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

Комментарии:

1. Я подозреваю, что ваше последнее предложение может быть правильным. Делаете ли вы что-нибудь для подключения sideMenuVC объекта к иерархии контроллера представления после создания экземпляра… или это делается с помощью обычной загрузки раскадровки?

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

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

4. Подключение с помощью раскадровки не работает, поэтому я пытаюсь сделать это с помощью кода. Знаете ли вы какой-либо другой код, который мог бы сработать?

5. и при использовании storyboard я имею в виду установку свойства делегата как IBOutlet и подключение его с помощью control drag.

Ответ №1:

Я нашел решение.

При использовании представлений контейнера правильный способ получения ссылок на встроенные VCS — это реализовать метод Prepare for segue и получить доступ к свойству назначения внутри класса VC, который содержит представления контейнера; вот так:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "sideVCSeg" {
            sideMenuVC = (segue.destination as! SideMenuViewController)
        }
        if segue.identifier == "centerVCSeg" {
            let navController = (segue.destination as! UINavigationController)
            centerVC = (navController.viewControllers.first as! centerViewController)
        }
    }
  

и поскольку этот метод выполняется при загрузке представления, мне нужно было только добавить эту строку в viewDidLoad :

 sideMenuVC?.delegate = centerVC