How to Share Data Between View Controllers and Other Objects in Swift

Swift 3 - Passing data between a View Controller and after that to another 2

Before calling presentViewController add :

nextViewController.name = yourTextField.text

You could also delete the segue call. That is redundant.

Here is an example that I've used in the past :

    @IBAction func doSegue(_ sender: UIButton) {
buttonTag = sender.tag

let storyboard = UIStoryboard (name: "Main", bundle: nil)
let resultVC = storyboard.instantiateViewController(withIdentifier: "ResultViewController")as! ResultViewController

// Communicate with new VC - These values are stored in the destination
// you can set any value stored in the destination VC here
resultVC.firstValue = buttonTag
resultVC.secondValue = randomOpponentValue()
self.navigationController?.pushViewController(resultVC, animated: true)
}

How to organize data shared between view controllers in swift

The approach you mentioned where you have a base view controller, is not a suitable one here and also deriving from it will create problems like duplicating the data and also potentially cause issues if you want to access data elsewhere from a non view controller.

You will need to have a model layer that will enable a controlled access to your model (data) objects. For instance, you can think of a model class say ChoiceManager and make it a Singleton.

class ChoiceManager{

//The singleton instance
static let sharedInstance = ChoiceManager()

var choices : [Choices] = []

//Logic to create Choice objects - may be parsing from a JSON, or from a network etc



}

Now across your project, you can access to the same ChoiceManager, by just saying

ChoiceManager.sharedInstance

And also access choices:

ChoiceManager.sharedInstance.choices

how to properly share a variable among some view controllers in swift?

I would recommend avoiding singletons here as well. The primary motivation is to make things testable. Here's a possible approach.

You have a User something like this:

struct User {
let userid: String
let email: String
}

Declare a protocol for managing your user. Using a protocol makes testing easier since you can create a mock that conforms to it.

protocol UserManagerProtocol {
func getSignedInUser() -> User?
func signIn(userid: String, password: String) -> User?
}

Declare your actual class that implements the protocol:

class UserManager: UserManagerProtocol {
fileprivate var signedInUser: User?
func getSignedInUser() -> User? {
return signedInUser
}
func signIn(userid: String, password: String) -> User? {
//call your server to sign in user
// if sign in fails, return nil
// if sign in works, create a User object
signedInUser = User(userid: userid, email: "email retrieved from server")
return signedInUser
}
}

Add a reference in your view controllers, but declare it using the protocol, not the actual class. Again, this allows for mocking.

class HomeVC: UIViewController {
var userManager: UserManagerProtocol?
}
class PostVC: UIViewController {
var userManager: UserManagerProtocol?
}

Finally, in your AppDelegate, when you launch the app, create a single instance of your UserManager, store it in the AppDelegate, and pass it to all your view controllers. In this example, I've obviously left out a lot of stuff because I don't know what your AppDelegate looks like.

class AppDelegate: NSObject, UIApplicationDelegate {
var userManager: UserManagerProtocol?

func applicationDidFinishLaunching(_ application: UIApplication) {
userManager = UserManager()

//when setting up your tab bar controllers, pass the userManager instance to each of them
}
}

passing data between view controllers without changing views

In your case, don't pass data.

Create a shared object to act as your data model. When users fill in the fields, update the data model.

When the user moves to the second controller/view, that controller uses the data model object to show what it needs to.

class FakeVC1 {
func userInput() {
DataModel.shared.username = "Me"
}
}

class FakeVC2 {
func viewAppears() {
if let name = DataModel.shared.username {
print(name)
} else {
print("I have nothing to say")
}
}
}

class DataModel {
static let shared = DataModel()
var username: String?
}

FakeVC1().userInput()
FakeVC2().viewAppears()

Getting data from another view controller (not via passing the data forward or backward) in Swift 4

Create a singleton class. let's say DataManager.

class DataManager: NSObject {

// A Singleton instance
static let shared = DataManager()

// your array
var dataArray = [String]()
}

now access this array from anywhere in the app.

Print(DataManager.shared.dataArray)


Related Topics



Leave a reply



Submit