I have a custom class named MenuBar
which is a UIView
used to present a UICollectionView
to a view controller. The problem I'm having is using a segue to another view controller when a UICollectionViewCell
is selected. Since MenuBar
is not a view controller, I can't seem to call performSegue()
. I created a segue in my storyboard between the two view controllers with an identifier. How can I properly trigger a segue from within my custom view class? How would this normally be done? I tried making a new instance of my view controller so that I could us the .performSegue()
from within the didSelectItemAt
collectionView
function but I don't think this is the proper way to do it at all. example:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = UARTModuleViewController()
vc.performSegue(withIdentifier: "colorSelection", sender: nil)
}
Any suggestions on how to perform the segue from within this function would be greatly appreciated. Below I will supply the key components of my existing code so that you can see what I'm doing. There is a lot more code in both classes but I think this should be enough for the general idea of what I'm trying to accomplish.
view controller:
class UARTModuleViewController: UIViewController, CBPeripheralManagerDelegate {
override func viewDidLoad() {
setupMenuBar()
}
let menuBar: MenuBar = {
let mb = MenuBar()
return mb
}()
private func setupMenuBar() {
view.addSubview(menuBar)
menuBar.translatesAutoresizingMaskIntoConstraints = false
menuBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
menuBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
menuBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
menuBar.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}
MenuBar.swift:
class MenuBar : UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
lazy var collectionView : UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor.clear
cv.dataSource = self
cv.delegate = self
return cv
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupCollectionView()
}
private func setupCollectionView() {
self.addSubview(collectionView)
collectionView.register(MenuCell.self, forCellWithReuseIdentifier: "MenuCell")
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.topAnchor.constraint(equalTo: topAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
collectionView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = UARTModuleViewController() // I want to perform a segue from here
vc.performSegue(withIdentifier: "colorSelection", sender: nil)
}
}
Thanks in advance to anyone who can provide helpful advice and suggestions!
This
let vc = UARTModuleViewController()
Creates another object on the fly that's independent of the presented one and may cause a crash if the vc isn't programmatically created , instead you need a delegate
lazy var menuBar: MenuBar = {
let mb = MenuBar()
mb.delegate = self
return mb
}()
And add this var inside MenuBar
weak var delegate:UARTModuleViewController?
Then use it like this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.performSegue(withIdentifier: "colorSelection", sender: nil)
}
Should say that a better approach for reusability is to create a protocol
protocol ColManager {
func navigate()
}
With
weak var delegate:ColManager?
And any class that wants to use should conform to the protocol and implement the navigate
method