When viewersTapped is clicked I want to pass the value of currentTitle from the storeViewController to the liveViewController by using a protocol.
Code Block language protocol labelMaker { func labelMaker(value: String) } class storeViewController: UIViewController { var labelDelegate: labelMaker! @IBAction func viewersTapped(_ sender: UIButton) { labelDelegate.labelMaker(value: sender.currentTitle!) } }
where it will be displayed within a label in the liveViewController.
Code Block language class liveViewController: UIViewController { let storeView = storeViewController() @IBOutlet var onlineViewers: UILabel! override func viewDidLoad() { super.viewDidLoad() storeView.labelDelegate = self } } extension liveViewController: labelMaker { func labelMaker(value: String) { onlineViewers.text = value }
But as soon as viewersTapped is clicked I am met with the error "Unexpectedly found nil while implicitly unwrapping an Optional value"
Thanks for your updated code. Your code is still missing storeButtonIsSelected, but many important things got clarified and I filled the missing part by guess.
So, your view hierarchy (transition structure) is something like this, OK?
(I have renamed all the type names with Capitalized identifiers if not yet. If you have some specific reason that you cannot follow this very common Swift coding rule, please re-interpret the type names.)
In this transition structure, you cannot use delegate pattern.
With using segue, the target view controllers will be instantiated at each transition, so once a view controller is dismissed, it is sort of not alive. But the delegate needs to be alive while the view controller using it is alive.
In other words, while StoreViewController is presented, there is no alive LiveViewController.
If you want to keep this transition structure, you may need to give up using delegate pattern.
Or else, you need to re-design the view hierarchy completely.
When keeping your transition structure, shared object would be a better strategy.
If you do not prefer this, you can utilize delegate pattern with making ViewController as a delegate, but it may need a little more complex code. (Please remember ViewController is still alive while StoreViewController is presented.)
By the way, some of your protocols SegueDestination, SourceForB and SourceForC are making your code more complex than it should be. That is making it very hard to read your code.
So, your view hierarchy (transition structure) is something like this, OK?
Code Block ViewContoller | +-(startLivePressed)---->Segue(id: segueToCamera)-> LiveViewController | ↑ | No direct segue connection | ↓ +-(storeButtonPressed)-->Segue(id: segueToStore)--> StoreViewController
(I have renamed all the type names with Capitalized identifiers if not yet. If you have some specific reason that you cannot follow this very common Swift coding rule, please re-interpret the type names.)
In this transition structure, you cannot use delegate pattern.
With using segue, the target view controllers will be instantiated at each transition, so once a view controller is dismissed, it is sort of not alive. But the delegate needs to be alive while the view controller using it is alive.
In other words, while StoreViewController is presented, there is no alive LiveViewController.
If you want to keep this transition structure, you may need to give up using delegate pattern.
Or else, you need to re-design the view hierarchy completely.
When keeping your transition structure, shared object would be a better strategy.
MyModel.swift:
Code Block import Foundation class MyModel { static let shared = MyModel() var labelTitle: String = "" }
StoreViewController
Code Block class StoreViewController: UIViewController { // var labelDelegate: LabelMaker! @IBAction func viewersTapped(_ sender: UIButton) { MyModel.shared.labelTitle = sender.currentTitle ?? "" // labelDelegate.labelMaker(value: sender.currentTitle!) } //... }
LiveViewController
Code Block class LiveViewController: UIViewController { // let storeView = StoreViewController() @IBOutlet weak var stopButton: UIButton! @IBOutlet var onlineViewers: UILabel! override func viewDidLoad() { super.viewDidLoad() // storeView.labelDelegate = self } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) onlineViewers.text = MyModel.shared.labelTitle } }
If you do not prefer this, you can utilize delegate pattern with making ViewController as a delegate, but it may need a little more complex code. (Please remember ViewController is still alive while StoreViewController is presented.)
By the way, some of your protocols SegueDestination, SourceForB and SourceForC are making your code more complex than it should be. That is making it very hard to read your code.