Pass data from the first VC to the third (Swift) - ios

I have 3 viewControllers and i'm passing data from the first to the second in this way (this is the first VC)
var steppers : UIStepper?
#IBOutlet weak var hourLabel: UILabel!
#IBOutlet weak var stepper: UIStepper!
#IBAction func stepper(_ sender: UIStepper) {
hourLabel.text = String(sender.value)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nc = segue.destination as? SelectClass {
nc.limit = Int(stepper.value)
} }
in the second VC i have the var limit = 0. Till here everything works well but what i want to do is to pass the value that the user gives to the stepper to the third VC. I tried to create another variable in the third VC var limit2 = 0and to pass the data in this way from the secondo VC to the third
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? ThirdClass {
vc.limit2 = limit
} }
but without results, my var limit2 = 0it always has the value 0 instead of taking the value that i added with the stepper. How can i do?
this is the prepare in the second VC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == nearbySearchSegueIdentifier {
guard let category = sender as? QCategoryy else {
return
}
if let selectedRows = tableView.indexPathsForSelectedRows {
if let vc = segue.destination as? ThirdClass {
vc.category = category
vc.limit2 = limit
}
}
}
}

Considering your current code, its possible that limit2 its not set because this condition is not valid:
// This condition could be failing sometimes
if let selectedRows = tableView.indexPathsForSelectedRows {
if let vc = segue.destination as? ThirdClass {
vc.category = category
vc.limit2 = limit
}
}
According to the Documentation, indexPathsForSelectedRows returns an optional and in your segue, you are only setting limit2 if that value is not nil.
Try to set limit2 outside any condition, so it will be executed always and if you need to fulfill a condition in order to do a segue, check shouldPerformSegue(withIdentifier:sender:) here.
Also, if the value that you need on VC3 is the same that you have when you leave VC1, there are different approaches that you could use to pass the data between them without having to rely on VC2.
One could be to create a static variable in VC1 and set the limit value before pushing to VC2:
var steppers : UIStepper?
#IBOutlet weak var hourLabel: UILabel!
#IBOutlet weak var stepper: UIStepper!
// ADD THIS
static var globalLimit: Int = 0
#IBAction func stepper(_ sender: UIStepper) {
hourLabel.text = String(sender.value)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nc = segue.destination as? SelectClass {
nc.limit = Int(stepper.value)
// AND THIS
VC1ClassName.globalLimit = Int(stepper.value)
}
}
Then inside VC3 load your global value whenever you want (maybe viewDidLoad):
override func viewDidLoad() {
super.viewDidLoad()
limit2 = VC1ClassName.globalLimit
}
Instead of having data passing through ViewControllers, you could also create a StepperManager class or something similar that is responsible for managing the data and you can access it from every class you need at any moment in time.

Why don't you just pass if from First to Second to Third?
FirstVC:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tosecondsegue" {
let itemController : Second = segue.destination as! Second
itemController.limit = 0 //Whatever you want
}
}
SecondVC:
var limit = 0
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tothirdsegue" {
let itemController : ThirdVC = segue.destination as! ThirdVC
itemController.limit2 = limit
}
}
ThirdVC:
var limit2 = 0
//Use it here now

Related

Passing data from a JSON array to another view controller

I'm trying to pass data from one view controller such as the name and trying to display it in the next view controller but I'm not sure how to do it. I'm using this API which is a JSON array to get the data for my app. I've looked all over for the answer to this but everything I try doesn't work. This is the code I'm using to try it right now but it doesn't work, this is in the first view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {`
if segue.identifier == "nextView" {
if let name = sender as? String, let nextView = segue.destination as? ListViewController {
nextView.nameText = name
}
}
}
This is the code in the destination view controller
class ListViewController: UIViewController {
#IBOutlet weak var name: UILabel!
var nameText: String = ""
override func viewDidLoad() {
super.viewDidLoad()
name?.text = nameText
}
}
The var you are trying to set in prepare nameText is a String so you should send it a String and not a [jsonList]
try like this :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "view" {
if let name = sender as? [jsonList], let nextView = segue.destination as! ListViewController {
nextView.nameText = //change affectation here
}
}
}

How to transfer label data to new controller label after label number is set with button

So how i transfer my ViewController label: totalPar to ThirdViewController label: totalPar5. And I want to transfer data that I have added there with my minus and plus buttons
Here is simulator pic that show what I want to transfer
My ThirdViewController is almost same as ViewController except prepare segue
Here is my ViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var totalPar: UILabel!
#IBOutlet weak var plusminusPar: UILabel!
#IBOutlet weak var currentPar: UILabel!
var totalPAR = Int()
var plusminusPAR = 0
var currentPAR = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func minusButton(_ sender: Any) {
totalPAR = Int(totalPar.text!)!
self.totalPar.text = String(totalPAR - 1)
plusminusPAR = Int(plusminusPar.text!)!
self.plusminusPar.text = String(plusminusPAR - 1)
currentPAR = Int(currentPar.text!)!
self.currentPar.text = String(currentPAR - 1)
}
#IBAction func plusButton(_ sender: Any) {
totalPAR = Int(totalPar.text!)!
self.totalPar.text = String(totalPAR + 1)
plusminusPAR = Int(plusminusPar.text!)!
self.plusminusPar.text = String(plusminusPAR + 1)
currentPAR = Int(currentPar.text!)!
self.currentPar.text = String(currentPAR + 1)
}
#IBAction func Seuraava(_ sender: Any) {
self.performSegue(withIdentifier: "next1", sender: Any?.self)
}
#IBAction func seiraava2(_ sender: Any) {
self.performSegue(withIdentifier: "seuraava2", sender: Any?.self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let thirdviewcontroller = segue.destination as! ThirdViewController
thirdviewcontroller.totalPAR5 = self.totalPAR
}
}
From the accepted answer and its comments you need to start improving your code and learn some concepts of data source in general.
For your case stop constantly converting string to integers to string. Choose one or the other:
class ViewController: UIViewController {
var totalPAR: Int = 0
var plusminusPAR: Int = 0
var currentPAR: Int = 0
Do natural operations on actions and separate methods:
#IBAction func minusButton(_ sender: Any) {
addToAll(valueToAdd: -1)
refreshLabels()
}
private func addToAll(valueToAdd: Int) {
totalPAR += valueToAdd
plusminusPAR += valueToAdd
currentPAR += valueToAdd
}
private func refreshLabels() {
self.totalPar.text = String(totalPAR)
self.plusminusPar.text = String(plusminusPAR)
self.currentPar.text = String(currentPAR)
}
Then you will have no issues calling
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let thirdviewcontroller = segue.destination as? ThirdViewController {
thirdviewcontroller.totalPAR = self.totalPAR
thirdviewcontroller.plusminusPAR = self.plusminusPAR
thirdviewcontroller.currentPAR = self.currentPAR
}
}
Now if in both view controllers you call refreshLabels on viewDidLoad the values are successfully transferred.
Simply make the variable in ThirdViewController and assign the value in prepare for segua and setup value to the label in viewDidLoad:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let thirdviewcontroller = segue.destination as! ThirdViewController
thirdviewcontroller.totalPAR5 = self.totalPAR
}
class ThirdViewController: UIViewController {
var totalPAR5 = 0
override func viewDidLoad() {
super.viewDidLoad()
self.totalPar.text = "\(totalPAR5+1)" //You can calculate here like +1 or -1
// Do any additional setup after loading the view.
}
}

Return array to another ViewController in Swift

I have two UIViewControllers and each one has an UITableView. Lets say that when I call from View-A to View-B, I take the cells which are marked in the UITableView in View-B and, after pressing a button I want to return an array with all the data selected from View-B to View-A, dismiss View-B and represent that information in the TableView of View-A.
How can I pass that array ? How do I have to reaload the data in View-A to show it after dimissing View-B ?
Any idea?
Thank you very much!!
protocol DataPasserDelegate {
func sendDatatoA(dataArrayFromB : Array<AnyObject>)
}
class ViewB: UIViewController {
var delegate: DataPasserDelegate!
var dataArrayB = Array<AnyObject>()
#IBAction func sendData(sender: Any){
self.dismiss(animated: true) {
self.delegate.sendDatatoA(dataArrayFromB: self.dataArrayB)
}
}
}
class ViewA: UIViewController, DataPasserDelegate {
#IBOutlet weak var tableViewA: UITableView!
var dataArrayA = Array<AnyObject>()
//MARK: - DataPasserDelegate
func sendDatatoA(dataArrayFromB: Array<AnyObject>) {
dataArrayA = dataArrayFromB
self.tableViewA.reloadData()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destVC = segue.destination as? ViewB{
destVC.delegate = self
}
}
}
So you can use prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "segueID") {
if let controller = segue.destination as? YourVC{
controller.array = yourArray
controller.tableView.reloadData()
}
}
}
You will need to use delegate for this. For more information on delegates you can go through my blog here.

Pass data from ViewController to TableViewController using segue

I have created a Calculator using Swift in Xcode. I would like to add another functionality to it, I already have a history label that displays the previous calculations. I would like to pass the data that displays in that history label into a TableViewController and for each calculation my history label shows to have it add each data into my TableViewController. I know I should be able to use perform segue, but I'm not exactly sure. Here is my code so far:
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var displayLabel: UILabel!
#IBOutlet weak var HistoryLabel: UILabel!
var userIsTypingNumbers = false
#IBAction private func NumbersEntered(_ sender: UIButton) {
//know what number is being pressed
let digit = sender.currentTitle!
//if user is typing a number, do this.
if userIsTypingNumbers{
//specify what number is being pressed
let textCurrentDisplay = displayLabel.text!
//append the another number onto the previous number.
displayLabel.text = textCurrentDisplay + digit
} else {
displayLabel.text = digit
}
userIsTypingNumbers = true
}
var displayValue: Double {
get {
return Double(displayLabel.text!)!
}
set {
displayLabel.text = String(newValue)
}
}
private var calculations = PerformCalculations()
#IBAction func Enter(_ sender: UIButton) {
//perform the calculations
if userIsTypingNumbers{
calculations.setOperand(operand: displayValue)
userIsTypingNumbers = false
}
if let mathematicalSymbol = sender.currentTitle {
calculations.performOperation(symbol: mathematicalSymbol)
}
HistoryLabel.text = HistoryLabel.text! + String(sender.currentTitle!);displayValue = calculations.result
HistoryLabel.text = HistoryLabel.text! + String(displayValue)
}
#IBAction func Clear(_ sender: UIButton) {
//clear display to 0.
displayLabel.text = "0"
HistoryLabel.text = ""
}
#IBAction func Delete(_ sender: UIButton) {
//deleting last typed number, if user messed up.
let name: String = self.displayLabel.text!
//count number of characters.
let stringLength = name.characters.count
let substringIndex = stringLength - 1
displayLabel.text = (name as NSString).substring(to: substringIndex)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "History"){
if let destinationVC = segue.destination as? HistoryClassViewController{
destinationVC
}
}
}
}
I have started attempting a prepare for segue function, but not sure how to make it work. Any help would be much appreciated. Hopefully this makes sense. Here is a picture of how my Calculator is laid out in Xcode:
Create in your HistoryClassViewController field like
var someData: Any!
Then:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "History" {
if let destinationVC = segue.destination as! HistoryClassViewController {
destinationVC.someData = something
}
}
}
Then to perform segue in place you wants to type this:
self.performSegue(withIdentifier: "History", sender: self)
Hope it helps
Here is thing Take one String Variable as global Variable in HistoryClassViewController class
example:
class HistoryClassViewController: UITableViewController{
var dataString:String!
//............Continue code
//............
Now Write this Method in ViewController class
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "History"){
if let destinationVC = segue.destination as? HistoryClassViewController{
destinationVC.dataString = displayLabel.text!
}
}
}
Finally access dataString value in TableViewController.

Change variable and send it to second view controller

I am creating a shop screen for my game. Where you can buy character for example. I need a variable to change when a button is pressed on the shop view and then for it to be sent to the next view controller. The second view controller will then select the correct player based on the value of the variable i have the following code for the shop view controller:
import Foundation
import UIKit
class Shop: UIViewController {
#IBAction func buttonPressed(_ sender: AnyObject){
var x = 1
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segue") {
let dest = segue.destination as! GameViewController
dest.x = x
}
}
}
But the variable is not global so how do i do it. Any advice would be much appreciated.
Based on your requirements I believe a global Singleton object is your best option.
A global singleton will allow you to access your shop data across controllers.
E.g.
class ShopManager {
static let sharedInstance = ShopManager()
var x = 0 // some initial value
private init() {} //Ensures singleton is unique
}
Now you can get/set ShopManager.sharedInstance.x (or any other variables/objects declared in the singleton class) anywhere without having to pass data between controllers.
import Foundation
import UIKit
class Shop: UIViewController {
#IBAction func buttonPressed(_ sender: AnyObject){
ShopManager.sharedInstance.x = 1
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segue") {
let dest = segue.destination as! GameViewController
//no need to set dest.x here. just access ShopManager.sharedInstance.x from the destination controller!
}
}
}
class ShopManager {
static let sharedInstance = ShopManager()
var x = 0 // some initial value
private init() {} //Ensures singleton is unique
}
You can store x as a variable in ShopViewController:
var x: Int?
#IBAction func buttonPressed(_ sender: AnyObject){
x = 1
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segueId") {
let dest = segue.destination as! GameViewController
dest.x = x
}
}
You can add a segue from one controller to another instead of an exact button and perform it from your callback:
#IBAction func buttonPressed(_ sender: AnyObject){
performSegue(withIdentifier: "segueId", sender: 1)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segueId") {
let dest = segue.destination as! GameViewController
dest.x = sender as! Int
}
}

Resources