Passing data to another ViewController without moving to the ViewController - ios

I have a sign up flow with different view controllers. I take input from user in ViewController1, move to the next view controller (ViewController2), and pass the data to the last view controller (for e.g ViewController5).
The issue is I can pass my data to the next view controller but I can’t pass it to the last view controller, as in:
// Move to Second View of the flow.
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: “SecondViewController“) as! SecondViewController
secondViewController.dataText = dataText!
self.navigationController?.show(secondViewController, sender: nil)
// Pass the data to the last View of the flow.
let fifthViewController = self.storyboard?.instantiateViewController(withIdentifier: “FifthViewController“) as! FifthViewController
fifthViewController.dataText = emailText!
The dataText would pass to the SecondViewController but not the FifthViewController. How do I achieve this?

you can use class and create singleton object to store data and retrieve
in fifth view controller
class SingletonClass {
var sharedInstance: SingletonClass {
struct Static {
static let instance = SingletonClass()
}
return Static.instance
}
var dataText : String = ""
}
now you can store data in singleton object like this as below
let singleTon = SingletonClass()
singleTon.sharedInstance.dataText = "store data"
and use like this in your fifthViewController
let singleTon = SingletonClass()
print(singleTon.sharedInstance.dataText)

In Your Appdelegate.swift file create a instance of FifthViewController like this
'var fifthViewController: FifthViewController?'
in your view controller from where you want to pass data
'let appDelegate = UIApplication.shared.delegate as! AppDelegate'
'
appDelegate.fifthViewController = self.storyboard?.instantiateViewController(withIdentifier: “ FifthViewController“) as! FifthViewController
appDelegate.fifthViewController.dataText = emailText!
'
when ever you want to push FifthViewController use Appdelegte refrence of this controller like this
'self.navigationController?.pushViewController(appDelegate.fifthViewController!, animated: true)'

Related

Get another tab's viewcontroller variable in current tab bar - iOS - Swift

I have a tabBarController with below hierarchy
TabBarController
Tab 1 -> Contains Navigation Controller(NavController1) -> ViewController1 -has--> ContainerView --contains--> DisplayedViewControllerTab1 (this is my tab1 view controller displayed)
Variable dataForVC1 is in DisplayedViewControllerTab1
When user taps Tab3 (DisplayedViewControllerTab3), I'm trying to get value of dataForVC1 to pass to tab3 viewController
So far I've tried this
In in TabBarController - didSelect method
var data: ModelData?
if let navController = tabBarController.viewControllers?[0] as? NavController1,
let childNavVC = navController.children.first as? ViewController1 {
//Get container view
let conView = childNavVC.containerView. //This is outlet
//Looking for something like this - struck here
if let displayedVC1 = "Container view's VC as? DisplayedViewControllerTab1 {
data = displayedVC1.dataForVC1
}
}
Kindly advice how to achieve this
You don't need to hustle around with container views. In your ViewController1 simply add references to the DisplayedViewControllerTab1 or other vc's you need and then access them directly.
Your VC code would look something like this.
class ViewController1: UIViewController {
//...
var displayedVC1: DisplayedViewControllerTab1?
//...
}
And then your code now:
var data: ModelData?
if let navController = tabBarController.viewControllers?[0] as? NavController1,
let childNavVC = navController.children.first as? ViewController1 {
data = childNavVC.displayedVc1
}
P.S. For convenience, if you have your own TabBarController class you can add all the references you need when the controller is created or simply have computed properties, so you don't need to go deep in the hierarchy all the time.
In your TabbarViewController class:
var myViewController1: MyViewControllerOne? {
return (viewControllers[0] as? NavController)?.children.first as? MyViewControllerOne
}
var myViewController2: MyViewControllerTwo? {
return (viewControllers[1] as? NavController)?.children.first as? MyViewControllerTwo
}

Instance Member Cannot Be Used on Type when pushing UIViewController

I am programmatically setting up ViewControllers (no storyboard).
I want to pass data to the next VC, and while I know how to do that with a segue and a storyboard, I can't figure out how to do it purely programmatically.
I get the error "Instance Member Cannot Be Used on Type..."
// Create Next View Controller Variable
let nextViewController = CarbonCalculatorResultsViewController()
// Pass data to next view controller. There is already a variable in that file: var userInformation: UserInformation?
CarbonCalculatorResultsViewController.userInformation = userInformation
// Push next View Controller
self.navigationController?.pushViewController(nextViewController, animated: true)
Do I need to instantiate the next VC before I can pass data? That's what this answer seems to talk about yet I don't have a Storyboard. Thanks!
Step 1: Setup your destination class
In CarbonCalculatorResultsViewController class, declare a var to receive data like so:
class CarbonCalculatorResultsViewController: UIViewController {
var foo: String? {
didSet {
// What you'd like to do with the data received
print(foo ?? "")
}
}
ovevride func viewDidLoad() {
//
}
}
Step 2: Prepare data in your source class
let nextViewController = CarbonCalculatorResultsViewController()
// You have access of the variable in CarbonCalculatorResultsViewController
nextViewController.foo = <data_you_want_to_pass>
// Push next View Controller
self.navigationController?.pushViewController(nextViewController, animated: true)
Then, every time the CarbonCalculatorResultsViewController comes alive, the didSet{} of foo would be called.
The current sample code (above) is setting a value to a static variable (owned by the CarbonCalculatorResultsViewController.Type.
What I believe you want to implement is the following instead:
// Create Next View Controller Variable
let nextViewController = CarbonCalculatorResultsViewController()
// Pass data to next view controller. There is already a variable in that file: var userInformation: UserInformation?
nextViewController.userInformation = userInformation
// Push next View Controller
self.navigationController?.pushViewController(nextViewController, animated: true)
This sample code is setting a value to the instance variable userInformation on the type nextViewController.
You should pass the variable on the Object, not on the Class
Replace: CarbonCalculatorResultsViewController.userInformation = userInformation
With:
nextViewController.userInformation = userInformation
Note:
CarbonCalculatorResultsViewController is the Class.
nextViewController is the Object.
Your full code should look like this:
// Create Next View Controller Variable
let nextViewController = CarbonCalculatorResultsViewController()
// Pass data to next view controller. There is already a variable in that file: var userInformation: UserInformation?
nextViewController.userInformation = userInformation
// Push next View Controller
self.navigationController?.pushViewController(nextViewController, animated: true)

How to pass data to nth view controller on the UINavigationController stack?

There are 2 apps A & B.
App A has a url to open App B.
Soon as App B opens, it has to load 5 view controllers onto the navigation stack which is done by the following code:
let LandingVC = self.storyboard?.instantiateViewControllerWithIdentifier("LandingVC") as! LandingVC
let Dashboard = self.storyboard?.instantiateViewControllerWithIdentifier("Dashboard") as! Dashboard
let PlayerVC = self.storyboard?.instantiateViewControllerWithIdentifier("PlayerVC") as! PlayerVC
let PlayerDetailVC = self.storyboard?.instantiateViewControllerWithIdentifier("PlayerDetailVC") as! PlayerDetailVC
let ScoreReportVC = self.storyboard?.instantiateViewControllerWithIdentifier("ScoreReportVC") as! ScoreReportVC
let viewControllersList = [LandingVC, Dashboard, PlayerVC, PlayerDetailVC, ScoreReportVC]
self.navigationController?.setViewControllers(viewControllersList, animated: false)
From ScoreReportVC I need to be able to set variables on previous ViewControllers so that the user can navigate to previous screens even though they fired the application from another application.
Here is what I have tried: defined a protocol in previous view controllers that are behind ScoreReportVC that are on the stack and inside ScoreReportVC like so:
for viewcontroller in self.navigationController?.viewControllers {
if viewcontroller is PlayerDetailVC {
PlayerDetailVC.delegate = self
}
if viewcontroller is PlayerVC {
PlayerVC = self
}
if viewcontroller is Dashboard {
Dashboard.delegate = self
}
if viewcontroller is LandingVC {
LandingVC.delegate = self
}
}
But the delegates are not getting called. Any help how to correctly pass data to all the ViewControllers on the stack would be greatly appreciated.
For relatable classes we use Delegations. But the classes which are not relatable , for those, we use Notifications. In your case Notifications will be needed for implementation and to pass data from one VC to another VC.
A better approach would be to create/set the variables when the controllers are created.

Navigation controller and remembering values

I have 2 view controller with navigation controller. First view controller has 4 text field and second view controller has 4 text field. To navigate first view controller to second I am using following code:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var destinationVC:UIViewController
destinationVC = storyboard.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC
navigationController?.show(destinationVC, sender: self)
To first from second view controller I am using
navigationController?.popViewController(animated: true)
However, even if the fields I have filled in first view controller keep the values when I go from first to second values I have written have disappear because of popviewcontroller method. What is the best way to remember values in second view controller?
You can have singleton where you can store the values as dictionary(or something else)
class Settings: NSObject {
static let shared = Settings()
public var dictionaryToStore: [String: String]?
private init() {
super.init()
}
}
And in your controller when poping
Settings.shared.dictionaryToStore = {"key1": textfield1.text, "key2": textfield2.text, ...
}
And in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
textfield1.text = Settings.shared.dictionaryToStore["key1"]
textfield2.text = Settings.shared.dictionaryToStore["key2"]
...
}
Also you can create custom object and store it.
EDIT 1 **
To have variables after app has been terminated you can save dictionary in UserDefaults
class Settings: NSObject {
static let shared = Settings()
public var dictionaryToStore: [String: String]? {
set(newValue) {
let defaults = UserDefaults.standard
defaults.set(newValue, forKey: "SomeKey")
}
get {
let defaults = UserDefaults.standard
let loadedValue = defaults.object(forKey: "SomeKey")
return loadedKey
}
}
private init() {
super.init()
}
}
The key reason for values not to be remembered on the SecondVC is that you're using new instances of SecondVC each time you open it.
So you better create an instance (first 3 lines of your code do that job) of SecondVC once, somewhere in the beginning of FirstVC, and use it in show() func everytime you need to show SecondVC instead of creating multiple instance of SecondVC each time.
In that case you'll see all values "remembered" in the SecondVC.
You can use key-value storage like NSUserDefaults in your secondViewController to save data when viewController will disappear and load on viewDidLoad. Or save your data in some struct/object instance and pass it when you push secondViewController.
if you want to pass data from you first view controller to second view
how to pass data from first viewcontroller to second viewcontroller
in above code though you are making new instance of you view controller still you can pass data by setting variable of second view controller in first view controller before
navigationController?.show(destinationVC, sender: self)
like
destnationVC.variableTOSet = valueTopass
and then
navigationController?.show(destinationVC, sender: self)
and then in second view controller use that variable to use value
so that how you can pass data from your first controller to second view controller
now if you want to pass data from your second viewController to first controller then you can use delegates

How to obtain reference to a View Controller from UITabBarViewController

EDIT: I was off base in my approach. I'm trying to pass data from one VC to another. The source VC is not controlled by a Tab Bar, so I can't reference the destination VC through it. I am attempting to reference the destination VC thorough the Storyboard, but the data is still nil on the destination VC. I'm using Core Data and wish to pass the ManagedObjectContext to another VC. Here is the code:
......
do {
try self.managedObjectContext.save()
appUserID = user.userID!
} catch {
fatalError("Error: \(error)")
}
}
}
self.passManagedObjectContext()
}
func passManagedObjectContext() {
let profileTableViewController = UIStoryboard(name: "Profile", bundle: nil).instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileTableViewController
profileTableViewController.managedObjectContext = self.managedObjectContext
}
I am passing data from the AppDelegate to other ViewControllers by referencing my TabBarViewControllers stack like so:
let tabBarController = window!.rootViewController as! UITabBarController
if let tabBarViewControllers = tabBarController.viewControllers {
let profileNavController = tabBarViewControllers[4] as! UINavigationController
let profileTableViewController = profileNavController.topViewController as! ProfileTableViewController
profileTableViewController.managedObjectContext = context
}
}
.....
END EDIT
I'm trying to do the same now but from one ViewController to another that is accessed through the tab bar (no segue). The code above does not recognize window!.rootViewController how can I reference the root UITabBarController?
UIViewController has a built-in optional property tabBarController, so inside your view controller you can access the tabBarController like so:
if let tabBarController = tabBarController {
//get the controller you need from
//tabBarController.viewControllers
//and do whatever you need
}
Here is the current list of properties available in the 'Getting Other Related View Controllers' section of Apple's UIViewController documentation:

Resources