Macos, Swift 3: How to Get Data Back After Segue

macOS, Swift 3: How to get data back after segue?

In macOS it's pretty easy if you are using storyboard and segues.

NSViewController has a property presenting which contains a reference to the parent view controller.

Obtain the reference, call a method in the parent view controller to pass the data and dismiss the child view controller.

let firstViewController = presenting as! FirstViewController
firstViewController.passDataBack(data)
self.dismiss(self)

Swift 3 - Get data back from segue

I think you're after an unwind segue.

To quote the docs:

...use the segue object to fetch the view controller being dismissed so that you can retrieve data from it.

Please see Creating an Unwind Segue on the View Controller Programming Guide for iOS.

Data not being passed through Segue

Yes, when your viewController is embedded in a UINavigationController you have to work through the parts of the chain until you get to the controller you want. Something like this should work:

override function prepare(for segue: UIStoryBoardSegue, sender: Any?) {
if segue.identifier == “TrackDetailVC” {
if let nav = segue.destinationVC as? UINavigationController {
if let detailsVC = nav.viewControllers[0] as? TrackDetailVC {
if let tr = sender as? newTracks {
detailsVC.track = tr
}
}
}
}
}

Swift passing calculated data back to previous view controller

My suggestion is to use a callback closure. It's less code and easier to handle than protocol / delegate.

In AddSubtractMoney declare a callback variable and call it in sendBackUpdatedNumber passing the Double value

class AddSubtractMoney: UIViewController {

// ...

var callback : ((Double)->())?

// ...

func sendBackUpdatedNumber(){

let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
callback?(amountPassedBackToUserInfo)
}
}

In prepare(for segue assign the closure to the callback variable and add the code to be executed on return

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.callback = { result in
print(result)
// do something with the result
}
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
}
}

How to pass data from modal view controller back when dismissed

Depending on the data you want to pass, you can create a property in the presenting view controller, which you can set when dismissing the modal view controller, so you can spare yourself the delegate.

For example, you have a ContactsViewController, holding a var contacts: [Contact] = [] property. When you want to create a new contact, you present a modal view controller with the different values you need to create a new Contact object. When you are done and want to dismiss the view controller, you call the function as you did in your code, but set the property in the ContactsViewController. It will look something like this:

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
if let presenter = presentingViewController as? ContactsViewController {
presenter.contacts.append(newContact)
}
dismiss(animated: true, completion: nil)
}

If you don't want to use a delegate, this is how you go about it:

In your OOTDListViewController :

var testValue: String = ""

@IBAction func printReceivedValue(_ sender: UIButton) {
print(testValue)
}

In your modal view controller (I'll call it PresentedViewController) :

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
// if your OOTDListViewController is part of a UINavigationController stack, this check will probably fail.
// you need to put a breakpoint here and check if the presentingViewController is actually a UINavigationController.
// in that case, you will need to access the viewControllers variable and find your OOTDListViewController
if let presenter = presentingViewController as? OOTDListViewController {
presenter.testValue = "Test"
}
dismiss(animated: true, completion: nil)
}

If you want to use a delegate, this is how to do it:

In your OOTDListViewController:

protocol ModalDelegate {
func changeValue(value: String)
}

class OOTDListViewController: ModalDelegate {

var testValue: String = ""
@IBAction func presentViewController() {
// here, you either create a new instance of the ViewController by initializing it, or you instantiate it using a storyboard.
// for simplicity, I'll use the first way
// in any case, you cannot use a storyboard segue directly, bevause you need access to the reference of the presentedViewController object
let presentedVC = PresentedViewController()
presentedVC.delegate = self
present(presentedVC, animated: true, completion: nil)
}

func changeValue(value: String) {
testValue = value
print(testValue)
}
}

In your PresentedViewController:

class PresentedViewController {
var delegate: ModalDelegate?
var testValue: String = ""

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
if let delegate = self.delegate {
delegate.changeValue(testValue)
}
dismiss(animated: true, completion: nil)
}

}

Pass data from one controller to another via segue and Navigation on different storyboard, Swift, iOS, Xcode

You must take into account the navigation controller in the next storyboard, so your prepare(for: sender:) function should look like this:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = (segue.destination as! UINavigationController).topViewController as! DestinationViewController
vc!.projectsSentT = ProjecctProd
vc!.logedInAsT = "Prod"
}

where DestinationViewController is the name of the second view controller embedded in the navigationController. And use segue.destination not and instance of the viewController directly.

MacOS Application Class data with segue

Instead of an IBAction, you can synchronize your menu item to a Boolean value in your user defaults simply by dragging a User Defaults Controller into the scene containing your menu bar, and then binding the "Value" binding of your menu item to the user defaults controller, with your defaults key in the "Model Key Path" field. I just tried this, and it seems to keep the value synced even when the menu item is also set to perform a segue.

xcode 8 swift: unwind segue transfer data is not working

You need to perform unwind and send data as following:

@IBAction func unwindToRaceViewController(sender: UIStoryboardSegue) 
{
if let sourceViewController = sender.sourceViewController
as? RaceViewController {
stat = sourceViewController.stat
}

You could refer to this article for unwind segues as alternative to delegate

You could also use delegates to pass data back to the previous controller.



Related Topics



Leave a reply



Submit