Home > Net >  iOS unwind segue breaking protocol/delegate. Why?
iOS unwind segue breaking protocol/delegate. Why?

Time:04-07

I have an iPhone app that presents information about a video playing on a kiosk-like device. The kiosk is running a python script that sends out video information via MQTT.

The iPhone uses CocoaMQTT to listen for video information. When the information (title etc.) is received the app presents it modally in NowPlayingVC with a segue from MenuVC. When the video is finished, the kiosk sends a 'finished' message and NowPlayingVC triggers an unwind segue to MenuVC. This process works fine the first time through, but fails after the first time.

To handle the MQTT communication I am using a shared instance of a model called MQTTManager that defines various protocol functions that are called in response to MQTT messages published by the kiosk. One of these functions is vhPlayingVideoInfoLoaded and provides the information about the playing video sent from the kiosk (e.g. MQTT Manager calls self.delegate?.vhPlayingVideoInfoLoaded!(description: String(descriptParts[1]), videoFile: String(descriptParts[0])))

After the first time through and the unwind segue MQTTManager does what it's supposed to, but MenuVC, the delegate of MQTTManager, stops responding as the delegate -- it's as if the unwind segue has broken the delegation.

As an experiment, I replaced the unwind segue with a storyboard segue from NowPlayingVC to MenuVC and everything work exactly as it should the first time and after. The problem with that approach is that one ends up with a big memory-consuming stack of VCs that are confusing to the user.

Can anyone explain why the unwind segue is breaking the protocol/delegate? Is there a way to fix it? I'm happy to provide code, but I am guessing, being self-taught, that I am missing an obvious issue with my approach.

I have tired to refresh the delegate by putting mqtt.delegate=self in various view functions, but that had no effect.

Any thoughts would be gratefully received, thanks. I'm using Xcode 13.3 and targeting iOS 13.

CodePudding user response:

Assuming:

  • your "present NowPlayingVC modally" segue has an identifier of "didStart"
  • your unwind segue has an identifier of "unwind"

You would have code along these lines:

class MenuVC: UIViewController, MQTTDelegate {
    
    let mqtt = MQTTObject.sharedInstance
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // set mqtt delegate to self
        mqtt.delegate = self
    }
    
    // mqtt sends a "player started playing" to its delegate (which is self)
    func didStart() {
        performSegue(withIdentifier: "didStart", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let vc = segue.destination as? NowPlayingVC {
            // set mqtt delegate to the segue destination controller
            mqtt.delegate = vc
        }
    }
    
    @IBAction func unwind( _ seg: UIStoryboardSegue) {
        // set mqtt delegate to self again
        mqtt.delegate = self
    }
}

class NowPlayingVC: UIViewController, MQTTDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // mqtt sends a "player finished playing" to its delegate (which is self)
    func didFinish() {
        performSegue(withIdentifier: "unwind", sender: self)
    }
}
  • Related