Change variable and send it to second view controller - ios

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

Related

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

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

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

Is it possible for a button to open into a specific tab when using the Tab Bar Controller?

The question is a little confusing to articulate so hopefully an image will be a little more helpful. Here's the setup:
So, I want the First View button to open the FirstViewController, and I want the Second View button to open the SecondViewController. If I link the Second View button to the SecondViewController like this:
I lose the tab navigation. And if I connect the button to the TabViewController like this:
then it will automatically open into the FirstViewController. Unless I'm missing something, it seems like this would need to be done with a little extra code but I cannot seem to find anything that explains how to do this.
Thank you!
Create storyboard segue from Viewcontroller to TabBarController with an identifier. Then assign selelctedIndex value of TabBarController in prepareforsegue method
#IBAction func firstBtnAction(_ sender: Any) {
(sender as! UIButton).tag = 0
performSegue(withIdentifier: "tabBar", sender: sender)
}
#IBAction func secBtnAction(_ sender: Any) {
(sender as! UIButton).tag = 1
performSegue(withIdentifier: "tabBar", sender: sender)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tabBar" {
if let vc = segue.destination as? UITabBarController {
vc.selectedIndex = (sender as! UIButton).tag
}
}
}
In tabViewController you need to implement following functions..
var index : Int!
#IBAction func button1(_ sender: Any) {
index = 1
self.performSegue(withIdentifier: "TabBarSegue", sender: self)
}
#IBAction func button2(_ sender: Any) {
index = 2
self.performSegue(withIdentifier: "TabBarSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "TabBarSegue"){
let videoController : TabBarController = segue.destination as! TabBarController
videoController.index = index
}
Then you need to implement TabBarController and implement following..
import UIKit
class TabBarController: UITabBarController {
var index : Int!
override func viewDidLoad() {
super.viewDidLoad()
selectedIndex = index
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

Finishing this snippet of code to pass data via a segue from one controller to another

I have a ViewController, "ViewController".
Within this view there is an attribute 'userEmailText.text' that I want to pass along to another view controller, "CreateNewCommunity"
I have a button connected to a segue with identifier 'createCommunitySegue'. I have create the code for when this is tapped:
#IBAction func createCommunityTapped(_ sender: AnyObject) {
self.performSegue(withIdentifier: "createCommunitySegue", sender: self)
}
In my second view controller, "CreateNewCommunity" I have a variable:
var myEmail: String?
and I have started to build the code ready to receive the data from the segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "createCommunitySegue" {
let createCommunityController: CreateNewCommunity = segue.destination as! CreateNewCommunity
createCommunityController.myEmail =
}
}
How do I finish this set-up so that the initial 'userEmailText.text' value is passed by "ViewController" through segue 'createCommunitySegue' into "CreateNewCommunity" view controller?
Thanks
Why not just
createCommunityController.myEmail = userEmailText.text
I think your problem is that you have a wrong idea of how to pass data from one vc to another.
The VC that you are passing data to doesn't recieve the data. It is the VC that has the data proactively pass the data to the VC that needs it.
My guess would be that you put this code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "createCommunitySegue" {
let createCommunityController: CreateNewCommunity = segue.destination as! CreateNewCommunity
createCommunityController.myEmail =
}
}
in the CreateNewCommunity controller! You should instead put the above in ViewController not CreateNewCommunity , and write
createCommunityController.myEmail = userEmailText.text
it should work.
VC1
#IBAction func createCommunityTapped(_ sender: AnyObject) {
self.performSegue(withIdentifier: "createCommunitySegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "createCommunitySegue" {
let createCommunityController: CreateNewCommunity = segue.destination as! CreateNewCommunity
createCommunityController.myEmail = userEmailText.text
}
}
VC2
var myEmail: String?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(myEmail)
}

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