Pass data from ViewController to TableViewController using segue - ios

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.

Related

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

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

store segued data on a separate viewcontroller (swift4)

My code takes text from a textfield and segues to a separate view controller. The problem is that it can only store 1 segue entry. The new one replace the old every time the button is pressed. How on vc2 can I store every new entry to the segue.
VC
import UIKit
class ViewController: UIViewController {
#IBOutlet var txt: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func pressButton(_ sender: Any) {
if txt.text != "" {
performSegue(withIdentifier: "segue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondController = segue.destination as! twoViewController
secondController.myString = txt.text!
}
}
twoVC
import UIKit
class twoViewController: UIViewController {
#IBOutlet var labelSmtih: UILabel!
var myString = String()
override func viewDidLoad() {
super.viewDidLoad()
labelSmtih.text = myString
}
}
If the second view controller is a UISplitViewController for example you should be able to append the text of the button to the label, by doing something in the lines of:
#IBAction func pressButton(_ sender: Any) {
if txt.text != "" {
performSegue(withIdentifier: "segue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondController = segue.destination as! twoViewController
secondController.myString += txt.text!
}
}
If you really have a separated view controller it will probably lose the data once you go back to the first VC. In that case, I suggest you save the current text of the label on viewWillDisappear of the 2nd VC and then retrieve this on the prepareforsegue function on the first VC. More info here: Swift: How to store user preferences?

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.
}
}

Send a string from a viewController to another one

Please, before you mark this question as duplicate, I want to know why my code is failing, not to be send to another one that is working.
I am a newbie in swift and I would like to send a variable "um_words" (which is calculated when a button is clicked) from a viewController when the same button is clicked, save that variable in the secondViewController and show it in a textView. To do so I have tried with many modifications of this code, which is giving no errors in the console but not showing the value of the variable on the textView:
1st VC
import UIKit
import Foundation
class TransViewController: UIViewController {
#IBOutlet var trad_text: UITextView!
#IBOutlet var buttonTrad: UIButton!
#IBOutlet var labelsitoh: UILabel!
var num_words = 0
#IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var DestViewController : PaymentViewController = segue.destination as! PaymentViewController
DestViewController.num_words = String(num_words)
}
}
override func viewDidLoad() {
super.viewDidLoad()
trad_text!.layer.borderWidth = 1
trad_text!.layer.cornerRadius = 20
trad_text!.layer.borderColor = UIColor(red:0.22, green:0.26, blue:0.39, alpha:1.0).cgColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
2nd VC
import UIKit
import Foundation
class PaymentViewController: UIViewController {
#IBOutlet var labelImport: UITextView!
var num_words = String()
override func viewDidLoad() {
super.viewDidLoad()
labelImport.text = num_words
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I have ab hypothesis of why it is not working: the function "prepare" is not being called; it only goes to next VC when the button is clicked...
Thank you for your time.
The func prepare should be outside of the button action, it will be called when segue is triggered.
#IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var DestViewController : PaymentViewController = segue.destination as! PaymentViewController
DestViewController.num_words = String(num_words)
}
See:
IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
self.performSegue(withIdentifier: "yourSegueIdentifier", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "yourSegueIdentifier") {
var destViewController : PaymentViewController = segue.destination as! PaymentViewController
destViewController.num_words = String(num_words)
}
}
You have create a function in another function...
Please try this.
PS: I did not test this code

override prepareForSegue doesn't work

SecondViewController's Code
#IBAction func ContinueFunc(_ sender: AnyObject) {
if (NomeAziendaText.text != "" && NumeroBlocchiText.text != "" && NumeroMacroText.text != ""){
nome = NomeAziendaText.text!
na = Int(NumeroMacroText.text!)!
nb = Int(NumeroBlocchiText.text!)!
Azienda.inizia(name: nome, numbermacro: na, numberblocchi: nb)
self.performSegue(withIdentifier: "next", sender: nil)
}
else {NomeAziendaText.text = ""
NumeroBlocchiText.text = ""
NumeroMacroText.text = ""
LabelAvvisi.text = " Inserisci tutti i valori"
}
/*
// MARK: - Navigation*/
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("pippa")
if (segue.identifier == "next"){
if let vc_destinazione = segue.destination as?{
vc_destinazione.stringaDiPassaggio = nome
}
}
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}`
ThirdViewController's Code
import UIKit
class ThirdViewController: UIViewController {
var stringaDiPassaggio: String = String()
var numero: Int = 0
#IBOutlet var Bottone: UIButton!
#IBOutlet var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
print(stringaDiPassaggio)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func FunzioneBottone(_ sender: AnyObject) {
}
}`
Why no data pass from SecondViewController to ThirdViewController?
If i override the method PrepareFor segue it show an error which say i doesn't override any method of super class
Help me please
make sure that you have connected the view controllers and correct this
performSegueWithIdentifier("next", sender: self)
then correct this
if (segue.identifier == "next"){
if let vc_destinazione = segue.destination as! ThirdViewController {
vc_destinazione.stringaDiPassaggio = nome
}
}
The signature should be
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
}
You have
func prepare(for segue: ...

Resources