Ula
Ula

Reputation: 177

Passing Data with without Segue from Container View to MainVC

Idea to send value trackNumber after pressing the button in the Container View(with ViewController) to Main ViewController to recivedTrackNumber without segue because they are in the same view. How to inform Main View controller(recivedTrackNumber) about the value of trackNumber ?

Container View(with ViewController) looks like that with button

 import UIKit
 class SelectSoundVC: UIViewController {

   var trackNumber: Int!

   @IBAction func winterSoundBut(_ sender: UIButton) {
    trackNumber = 1

  } 

}

and Main ViewController

class MainVC: UIViewController {

   var recivedTrackNumber: Int!

}

Main.storyboard Screenshot

Upvotes: 0

Views: 1684

Answers (3)

unixb0y
unixb0y

Reputation: 1048

Third method ;-)
If you instantiate the second view controller from code (from the MainVC), then you could access that variable easily:

let selectSoundVC = SelectSoundVC()
recivedTrackNumber = selectSoundVC.trackNumber
present(selectSoundVC, animated: true, completion: nil)

This should work!

Upvotes: 0

pacification
pacification

Reputation: 6018

Delegate pattern should help you. First of all you need the delegate protocol:

protocol SelectSoundVCDelegate {
    func didSelectTrackNumber(_ trackNumber: Int)
}

with func that accept the trackNumber value. Next, you need to create delegate property in SelectSoundVC:

class SelectSoundVC: UIViewController {

    weak var delegate: SelectSoundVCDelegate?
    var trackNumber: Int!

    @IBAction func winterSoundBut(_ sender: UIButton) {
        trackNumber = 1
        delegate?.didSelectTrackNumber(trackNumber)
    } 

}  

that will be call the didSelectTrackNumber in @IBAction. Note that delegate property should be weak to avoid reference cycles. The last step, in MainVC you should set delegate property of SelectSoundVC:

selectSoundVC.delegate = self  

This part is little bit tricky, because you need the instance of SelectSoundVC to set the delegate. You can set it in prepareFoSegue method, for example:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let viewController = segue.destination as? SelectSoundVC, segue.identifier == "SelectSoundVC" {
        viewController.delegate = self
    }
}

Upvotes: 3

michael-martinez
michael-martinez

Reputation: 797

You can use prepareForSegue(_:) to retrieve a strong reference to your embedded view controller at initialization. Just set your segue identifier to "EmbedSegue" in Storyboard

// MainVC
private var embeddedViewController: SelectSoundVC?

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let vc = segue.destination as? SelectSoundVC,
        segue.identifier == "EmbedSegue" {
        self.embeddedViewController = vc
    }
}

Also change your track property to an optional as no track can be selected.

// SelectSoundVC
var trackNumber: Int?

Then from anywhere in your MainVC you can retrieve your track number :

// Here you can access to the trackNumber property, no need to duplicate its value (Single Responsability)
if let embeddedViewController = self.embeddedViewController, let trackNumber = embeddedViewController.trackNumber {
    print("Track Number \(trackNumber)")
}

Upvotes: -1

Related Questions