#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