16

I tried creating global variables and updating the information when the view is loaded but data isn't being rendered.

GLOBAL VARIABLES

var viewName:String = ""
var viewDuration:String = ""
var viewPeriod:String = ""
var viewMinAmp:String = ""
var viewMaxAmp:String = ""
var viewStep:String = ""
var viewType:String = ""

Is there a more efficient way of passing information other than having global variables?

@IBOutlet var txtName: UITextField!
@IBOutlet var txtDuration: UITextField!
@IBOutlet var txtPeriod: UITextField!
@IBOutlet var txtMinAmp: UITextField!
@IBOutlet var txtMaxAmp: UITextField!
@IBOutlet var txtStep: UITextField!
@IBOutlet var txtType: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    setInfo(viewName, duration: viewDuration, period: viewPeriod, minAmp: viewMinAmp, maxAmp: viewMaxAmp, step: viewStep, type: viewType)
}

func setInfo(name: String, duration: String, period: String, minAmp: String, maxAmp: String, step: String, type: String) {
    txtName.text = name
    txtDuration.text = duration
    txtPeriod.text = period
    txtMinAmp.text = minAmp
    txtMaxAmp.text = maxAmp
    txtStep.text = step
    txtType.text = type
}
5
  • 4
    Define properties in UIViewControllers and set them when initializing that controller. Don't use global variables, its a bad practice here. Commented Aug 9, 2014 at 5:28
  • How do I access methods from a controller from another controller? @AndrewShmig Commented Aug 10, 2014 at 18:17
  • how do you access other methods in Swift? :) Commented Aug 10, 2014 at 20:03
  • possible duplicate of How do you share data between view controllers and other objects in Swift? Commented Jun 19, 2015 at 14:25
  • See this answer for a basic example. Commented Aug 11, 2015 at 6:38

5 Answers 5

34

One solution would be to override prepareForSegue(segue:sender:) from within the view controller which contains the data that you wish to pass to the destination view controller.

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if (segue.identifier == "YourSegueName") {
        //get a reference to the destination view controller
        let destinationVC:ViewControllerClass = segue.destinationViewController as! ViewControllerClass

        //set properties on the destination view controller
        destinationVC.name = viewName
        //etc...
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

does this work in Swift 2.1 ? I used exact same code and I get "Cannot convert value of type UIViewController to specified type NextViewController"
I haven't tried it in Swift 2.1 yet; however, it sounds like you may need explicitly cast the destination view controller. let destinationVC:ViewControllerClass = segue.destinationViewController as ViewControllerClass
This still needs the use of Global variables. Any ideas on how to avoid global variables for passing data between view controllers or rather avoid shared state
Why does creating a copy of the ViewControllerClass change the properties of the real thing?
24

For Swift 3.0

final class Shared {
     static let shared = Shared() //lazy init, and it only runs once

     var stringValue : String!
     var boolValue   : Bool!
}

To set stringValue

Shared.shared.stringValue = "Hi there"

to get stringValue

 if let value = Shared.shared.stringValue {
        print(value)
 }

For Swift version below 3.0

You can pass data between views using singleton class. It is easy and efficient way. Here is my class ShareData.swift

import Foundation

class ShareData {
    class var sharedInstance: ShareData {
        struct Static {
            static var instance: ShareData?
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            Static.instance = ShareData()
        }

        return Static.instance!
    }


    var someString : String! //Some String

    var selectedTheme : AnyObject! //Some Object

    var someBoolValue : Bool!
}

Now in my ViewControllerOne I can set above variable.

//Declare Class Variable

let shareData = ShareData.sharedInstance

override func viewDidLoad() {
    self.shareData.someString ="Some String Value"
}

And in my ViewControllerTwo I can access someString as

let shareData = ShareData.sharedInstance
override func viewDidLoad() {
    NSLog(self.sharedData.someString) // It will print Some String Value
}

9 Comments

this is just a new blank project
This sounds the right approach specially if instance is of something unique in the application for example userInfo, only one use can be logged in at a time and so can be a shared singleton instance.
I like this way to share data between controller! But since swift3.0 has many changes in grammar. Could you please update a swift3.0 version on this?@SaqibOmer
Am getting error on line: " static var token: dispatch_once_t = 0 " " 'dispatch_once_t' is unavailable in Swift: Use lazily initialized globals instead"
@PhilipS Which version of Swift you are using? And what is error?
|
5

Personally, I prefer ways as follow:

  • If you want to jump forward between two view controllers (from A to B), as -pushViewController:animated: in navigation, you can define a property of model for Controller B and expose it publicly, then set this property explicitly before jumping from Controller A, it's pretty straightforward;

  • In case you want to jump backward from Controller B to A, use Delegate+Protocol mode. Controller B drafts a public protocol and own a "delegate" property, any object who would like to be the delegate of Controller B shall comply and implement its protocol(optionally). then prior to the jumping-backward, Controller B makes its delegate perform certain action(s) listed in protocol, the data could be transferred in this way;

  • Under certain circumstance, you may want to transfer data from a Controller(or controllers) to other multiple Controllers, use Notification mechanism if this is the case.

Apple has detailed instructions about delegate mode, notification mode in official documentation, check them out in XCode, :)

Comments

1

Just need to follow 3 steps, let's assume you want to pass data from ViewControllerA to ViewControllerB:

  1. create a segue between ViewControllerA and ViewControllerB
  2. name the segue with a Identifier in the attributes inspector of it
  3. override the prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) at ViewControllerA

For step#3,:

  • if you are not using swift 2.1, please follow @Scott Mielcarski 's answer at this question
  • for people who are using swift 2.1, or who get error "Cannot convert value of type 'UIViewController' to specified type 'your view Controller class name', After following @Scott Mielcarski 's answer at this question, Please use:let destinationVC:ViewControllerClass = segue.destinationViewController as! ViewControllerClass instead of let destinationVC:ViewControllerClass = segue.destinationViewController

    This is tested on Swift 2.1.1 and it works for me.

Comments

0

If you don't actually want to pass data between view controllers but rather simply want to store a global variable you can do this:

This gives a great explanation for how to do this in Swift 5: https://www.hackingwithswift.com/example-code/system/how-to-save-user-settings-using-userdefaults

Summary:

To set a value:

let defaults = UserDefaults.standard
defaults.set("value", forKey: "key")

To get a String value:

let key = defaults.object(forKey: "StringKey") as? [String] ?? [String]()

To get integer value:

let key = defaults.integer(forKey: "IntegerKey")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.