2

I am developing an app in Swift that, in gist, tells people the price of Bitcoin in various currencies. To select the currency, the user chooses from a list in a view controller with a UITableView. This is currencyViewController, and it is presented from my main screen, viewController.

What I want to happen is that, when the user dismisses currencyViewController, it passes a string to a UIButton in the main viewController.

Here's the prepareForSegue function that should pass the data:

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "presentCurrency") {

        currencySelector.setTitle("\currencySelected", forState: UIControlState.Normal)

    }
}

CurrencySelector is a UIButton in the main viewController, and currencySelected is a variable in the second view controller, currencyViewController.

It gives the error "Invalid Escape Sequence In Literal"

So, I've narrowed it down to one of two issues:

  1. The variables from viewController can't be "seen" from currencyViewController. If so, how can I modify the text of CurrencySelector from CurrencyViewController?

  2. For some reason, when the user exits the pushed CurrencyViewControler, prepareForSegue isn't called.

What is going on here? Thanks, and apologies - I am but a swift newbie.

Juan Boero
  • 6,281
  • 1
  • 44
  • 62
rocket101
  • 7,369
  • 11
  • 45
  • 64
  • 1
    If you want prepareForSegue to be called when you go back to the first controller, you need to go back with an unwind segue. – rdelmar Oct 12 '14 at 15:55

2 Answers2

14

2 - "prepareForSegue" is called when you push a new view controller via the segue, but not when you dismiss it. No segue is called upon dismissal.

1 - A good way to do this would be the delegate pattern.

So the main view controller would be the delegate for the currencyViewController, and would receive a message when that controller is dismissed.

In the start of the currencyViewController file you prepare the delegate:

protocol CurrencyViewControllerDelegate {
  func currencyViewControllerDidSelect(value: String)
}

and you add a variable to the currencyViewController:

var delegate : CurrencyViewControllerDelegate?

Now, the mainViewController has to conform to that protocol and answer to that function:

class MainViewController : UIViewController, CurrencyViewControllerDelegate {
  //...  

  func currencyViewControllerDidSelect(value: String)  {
    //do your stuff here
  }
}

And everything is prepared. Last steps, in prepareForSegue (MainViewController), you will set the delegate of the currencyViewController:

var currencyVC = segue.destinationViewController as CurrencyViewController
currencyVC.delegate = self;

And when the user selects the value in currencyViewController, just call that function in the delegate:

self.delegate?.currencyViewControllerDidSelect("stuff")

A bit complex maybe, but it's a very useful pattern :) here is a nice tutorial with more info if you want it:

http://www.raywenderlich.com/75289/swift-tutorial-part-3-tuples-protocols-delegates-table-views

rocket101
  • 7,369
  • 11
  • 45
  • 64
Tiago Lira
  • 2,543
  • 1
  • 18
  • 17
  • It may be a bit complex for a pattern, but it is definitely really cool and shows some of the powers in iOS development. – David Feb 06 '15 at 05:11
4

You have to use the parantheses to eval variables in strings, i.e. println("\(currencySelected)")

To access variables in the second view controller (the one which is the destination of the segue) you have to get a reference to it:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "presentCurrency") {
        let currencyViewController = segue.destinationViewController as CurrencyViewController // the name or your class here

        currencySelector.setTitle("\(currencyViewController.currencySelected)", forState: UIControlState.Normal)

    }
}
zisoft
  • 22,770
  • 10
  • 62
  • 73