Trouble passing int data from one view controller to another (segue) [duplicate] - ios

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 3 years ago.
I would like to pass an int data from one view controller to another one.
The problem is that the int data received in the second view controller doesn't match the first view controller's int data.
View controller 1:
import UIKit
class levelsSelector: UIViewController {
var levelSelected: Int = 0
var gameWanted: Int = 0
#IBAction func level1Tapped(_ sender: Any) {
gameWanted = 1
performSegue(withIdentifier: "gameOn", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gameOne" {
let levelsSelector = segue.destination as! game
levelsSelector.finalGame = levelSelected
let levelsSelector2 = segue.destination as! game
levelsSelector2.finalLevel = gameWanted
}
}
}
View controller 2:
import UIKit
class game: UIViewController {
var finalLevel: Int = 0
var finalGame: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
print(finalLevel)
print(finalGame)
}
}

You've made a typo in your segue name
performSegue(withIdentifier: "gameOn", sender: self)
...
if segue.identifier == "gameOne" {
these two identifiers need to match

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? game {
destination.finalGame = levelSelected
destination.finalLevel = gameWanted
}
Also, check: your seque identifier on a storyboard should match a string in: perform segue method

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 can I use one var or let from a view controller to another view controller

I made a popup view controller but now I'm trying to pass the data from the popup to the view controller via prepare function. Let's take a look.
// this is from the pop up view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let toBeMoved :ViewController = segue.destination as! ViewController
toBeMoved.enterVC()
amountEntered.text = "\(runningNumber1)"
}
// and I added a func in my main VC but I can't get the var in the VC
// totalCash is a label to be changed when the amount is entered from the
// pop up vc
func enterVC () {
totalCash.text = "\(amountEntered)"
}
I added enterVC to viewDidLoad.
Try this and see:
class TestVC: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let toBeMoved :ViewController = segue.destination as! ViewController
toBeMoved.amountEntered = runningNumber1
toBeMoved.enterVC()
}
}
class ViewController: UIViewController {
var amountEntered: Int = 0
func enterVC () {
totalCash.text = "\(amountEntered)"
}
}
or try this also.
class TestVC: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let toBeMoved :ViewController = segue.destination as! ViewController
toBeMoved.enterVC(amountEntered: runningNumber1)
}
}
class ViewController: UIViewController {
func enterVC (amountEntered: Int) {
totalCash.text = "\(amountEntered)"
}
}
//Turns out I needed to put a guard let in order to make this work also added IBAction in the original view controller like so:
class ViewController : UIViewController {
#IBAction func didUnwindSegue (sender: UIStoryboardSegue){
guard let realVC = sender.source as? ViewController else {
return
}
}
}
class TestVC : UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let realVC = segue.destination as? ViewController else {
return
}
realVC.totalCash.text = runningNumber1
}
}

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

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

Prepare for Segue in Swift

I'm facing the error message:
"UIStoryboardSegue does not have a member named 'identifier'"
Here's the code causing the error
if (segue.identifier == "Load View") {
// pass data to next view
}
On Obj-C it's fine using like this:
if ([segue.identifier isEqualToString:#"Load View"]) {
// pass data to next view
}
What am I doing wrong?
This seems to be due to a problem in the UITableViewController subclass template. It comes with a version of the prepareForSegue method that would require you to unwrap the segue.
Replace your current prepareForSegue function with:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "Load View") {
// pass data to next view
}
}
This version implicitly unwraps the parameters, so you should be fine.
Swift 4, Swift 3
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MySegueId" {
if let nextViewController = segue.destination as? NextViewController {
nextViewController.valueOfxyz = "XYZ" //Or pass any values
nextViewController.valueOf123 = 123
}
}
}
I think the problem is you have to use the ! to unbundle identifier
I have
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue!.identifier == "Details" {
let viewController:ViewController = segue!.destinationViewController as ViewController
let indexPath = self.tableView.indexPathForSelectedRow()
viewController.pinCode = self.exams[indexPath.row]
}
}
My understanding is that without the ! you just get a true or false value
For Swift 2.3,swift3,and swift4:
Create a perform Segue at didSelectRowAtindexPath
For Ex:
self.performSegue(withIdentifier: "uiView", sender: self)
After that Create a prepareforSegue function to catch the Destination segue and pass the value:
Ex:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "uiView"{
let destView = segue.destination as! WebViewController
let indexpath = self.newsTableView.indexPathForSelectedRow
let indexurl = tableDatalist[(indexpath?.row)!].link
destView.UrlRec = indexurl
//let url =
}
}
You need to create a variable named UrlRec in Destination ViewController
Swift 1.2
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "ShowDeal") {
if let viewController: DealLandingViewController = segue.destinationViewController as? DealLandingViewController {
viewController.dealEntry = deal
}
}
}
Prepare for Segue in Swift 4.2 and Swift 5.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "OrderVC") {
// pass data to next view
let viewController = segue.destination as? MyOrderDetailsVC
viewController!.OrderData = self.MyorderArray[selectedIndex]
}
}
How to Call segue On specific Event(Like Button Click etc):
performSegue(withIdentifier: "OrderVC", sender: self)
this is one of the ways you can use this function, it is when you want access a variable of another class and change the output based on that variable.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let something = segue.destination as! someViewController
something.aVariable = anotherVariable
}
Provided you aren't using the same destination view controller with different identifiers, the code can be more concise than the other solutions (and avoids the as! in some of the other answers):
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if let myViewController = segue.destinationController as? MyViewController {
// Set up the VC
}
}
Change the segue identifier in the right panel in the section with an id. icon to match the string you used in your conditional.
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if(segue!.identifier){
var name = segue!.identifier;
if (name.compare("Load View") == 0){
}
}
}
You can't compare the the identifier with == you have to use the compare() method

Resources