This question arises constantly.
One suggestion is to create a singleton data container: an object that is created once and only once in the life of your application and stored for the duration of your application.
This approach is well suited for situations where you have global application data that must be accessible / modifiable for different classes in your application.
Other approaches, such as setting up one-way or two-way links between view controllers, are better suited for situations where you transfer information / messages directly between view controllers.
(see nhgrif answer below for other alternatives.)
With a singleton data container, you add a property to your class that holds a reference to your singleton, and then use this property anytime you need access.
You can configure your singleton so that it saves its contents to disk so that your application state is maintained between starts.
I created a demo project on GitHub demonstrating how you can do this. Here's the link:
SwiftDataContainerSingleton project on GitHub Here is the README from this project:
SwiftDataContainerSingleton
Demonstration of using data container syntax to preserve application state and share it between objects.
The DataContainerSingleton class is a valid singleton.
It uses the sharedDataContainer static constant to maintain a link to a singleton.
To access the singleton, use the syntax
DataContainerSingleton.sharedDataContainer
An example project defines 3 properties in a data container:
var someString: String? var someOtherString: String? var someInt: Int?
To load the someInt property from a data container, you must use the following code:
let theInt = DataContainerSingleton.sharedDataContainer.someInt
To save the value of someInt, you must use the syntax:
DataContainerSingleton.sharedDataContainer.someInt = 3
The DataContainerSingleton init method adds an observer for UIApplicationDidEnterBackgroundNotification . This code is as follows:
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName( UIApplicationDidEnterBackgroundNotification, object: nil, queue: nil) { (note: NSNotification!) -> Void in let defaults = NSUserDefaults.standardUserDefaults()
In observer code, it stores the properties of the NSUserDefaults data NSUserDefaults . You can also use NSCoding , Core Data, or various other ways to store state data.
The DataContainerSingleton init method also attempts to load stored values for its properties.
This part of the init method looks like this:
let defaults = NSUserDefaults.standardUserDefaults() //----------------------------------------------------------------------------- //This code reads the singleton properties from NSUserDefaults. //edit this code to load your custom properties someString = defaults.objectForKey(DefaultsKeys.someString) as! String? someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String? someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int? //-----------------------------------------------------------------------------
The keys for loading and saving values in NSUserDefault are stored as string constants, which are part of the DefaultsKeys structure, defined as follows:
struct DefaultsKeys { static let someString = "someString" static let someOtherString = "someOtherString" static let someInt = "someInt" }
You are referring to one of the following constants:
DefaultsKeys.someInt
Using singleton data container:
This sample application uses the three way syntax of the data container.
There are two view controllers. The first is a custom subclass of UIViewController ViewController , and the second is a custom subclass of UIViewController SecondVC .
Both view managers have a text field on them, and both load the value from the singlelton someInt someInt data container into the text field in their viewWillAppear method and both store the current value from the text field back to the `someInt 'data container.
The code for loading the value into the text field is in the viewWillAppear: method:
override func viewWillAppear(animated: Bool) {
The code for saving the user-modified value back to the data container is in the dispatcher methods of the textFieldShouldEndEditing type:
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
You must load the values into your user interface in viewWillAppear and not in viewDidLoad so that your user interface is updated every time the view controller is displayed.