Button state info - ios

The question is similar to "how to pass data from different viewController" but in this case I need another information, I know how to pass the data from one viewController to another but I don't know how to tell to the second viewController a specific state of an object that is in the first view. In my case I have some buttons in the first view that go in.
button.isHidden = true
after the tap, I want to tell to the second viewController which buttons have been tap, maybe I've to create a variable that represents the status of the button, but I don't know how to do, someone can help me?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToLast" {
guard let vc = segue.destination as? FinalClass else { return }
let guest = segue.destination as! FinalClass
if let user = sender as? User {
}
}
}
where User can be something like
struct User {
var button1 = Button1 tapped
var button2 = Button2 tapped
ecc.
}

Let suppose you have two viewControllers - FirstViewController and SecondViewController.
So First,
Let Declare two Arrays in FirstViewController and SecondViewController something like -
var tappedButtonsArray = NSMutableArray() // In 'FirstViewController'
AND
var previousViewTappedButtonsArray = NSMutableArray() // In 'SecondViewController'
And here is my code to add | remove tapped buttons to | from tappedButtonsArray in FirstViewController -
#IBAction func btnTapped(_ sender: UIButton) { // Single action for all buttons
if (tappedButtonsArray.contains(sender)){
tappedButtonsArray.remove(sender) // Remove previous tapped button on unselect
}
else{
tappedButtonsArray.add(sender) // Add tapped button on select
}
}
And Here is your perform segue method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToLast" {
guard let secondViewController = segue.destination as? SecondViewController else { return }
secondViewController.previousViewTappedButtonsArray = tappedButtonsArray
}
}
I've done with a simple array concept without any model, so that you can understand the follow. I hope it'll help you to start with.

Related

Downcasting Any? to UIBarButtonItem

override func prepare(for segue: UIStoryboardSegue, sender:
Any?) {
if segue.identifier == "detailSegue" {
let indexPath = tableView.indexPathForSelectedRow!
let card = cards[indexPath.row]
let detailTableViewController = segue.destination as! DetailTableViewController
detailTableViewController.card = card
detailTableViewController.picture = card.image
} else if segue.identifier == "addEditSegue" {
let addEditTableViewController = segue.destination as! AddEditTableViewController
let buttonPressed = sender as? UIBarButtonItem
if buttonPressed == cardsAddButton {
addEditTableViewController.isNewCard = true
} else {
addEditTableViewController.isNewCard = false
}
}
}
Hi, I am new to Swift. I need to perform the same segue by either tapping a UIBarButtonItem (cardsAddButton) or by tapping on cells of a UITableView. Using print statements I found that buttonPressed is nil when I tap cardsAddButton. Why? How should I check what was the sender?
You – the developer – should know who the sender of prepare(for is. There are only three possibilities:
If the segue is connected to the table view cell in Interface Builder then the sender is the UITableViewCell.
If the segue is connected to the view controller in Interface Builder then the sender is the UIViewController.
If performSegue is called in code then the sender is whatever you passed in the sender parameter (including nil).
Your code can work only if you call performSegue in the IBAction of the button and pass the button instance as sender
#IBAction func addCard(_ sender : UIBarButtonItem)
{
self.performSegue(withIdentifier:"addEditSegue", sender: sender)
}

swift button press action loads tableview controller twice

I have a MeterTableviewController connected to two tableview controllers with two segues. The first segue LocationListSegue is connected from a button on the MeterTableviewController directly to the LocationListTableViewController. Another segue MetersListSegue connected from the top of the MeterTableViewController to the
MeterListTableviewController.
When I press on the location button, the LocationListTableViewController gets loaded twice.
I thought it is because I was calling it twice: once from the button IBAction and another time on Prepare, so I commented the code from Prepare, but it still loads it twice.
However the MeterListTableViewController gets loaded only once.
I dont know why the button press loads the controller twice. Can someone tell me?
#IBAction func chooseLocation(_ sender: Any) {
self.performSegue(withIdentifier: "LocationListSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
/*
if segue.identifier == "LocationListSegue"{
let viewController:LocationListTableViewController = segue.destination as! LocationListTableViewController
}
*/
if segue.identifier == "MetersListSegue"{
let viewController2:MeterListTableViewController = segue.destination as! MeterListTableViewController
}
}
You have added a segue as well as segue action from button, remove one of them
Remove story board segue and change your code with my code. This is enough for you.
#IBAction func chooseLocation(_ sender: Any) {
let tableViewController = self.storyboard?.instantiateViewController(withIdentifier: "your identifier") as! MeterListTableViewController
self.navigationController?.pushViewController(tableViewController, animated: true)
}
If you want to use segue remove IBAction for UIButton and write this code.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "LocationListSegue"{
let viewController:LocationListTableViewController = segue.destination as! LocationListTableViewController
} else if segue.identifier == "MetersListSegue"{
let viewController2:MeterListTableViewController = segue.destination as! MeterListTableViewController
}
}

Trouble passing variable through segue (Swift)

I have a variable called correctAnswers = 0 at the top of my program, I have a function where every time it is called it adds 1 to the correctAnswers value. I tested that the function was actually changing the variable by making it print after every +1 and sure enough it goes 1, 2, 3, 4 and so on. However I have an end screen that shows the results after the program has reached its limit of questions (10 in this case)
EDIT #2: Here is my prepare for segue function
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "EndScreenSegue") {
let secondViewController = segue.destination as! EndScreen
correctAnswers = sender as! Int
secondViewController.gso = self
}
}
And here is the code in my end screen:
var gso: GameScreen?
override func viewDidLoad() {
super.viewDidLoad()
gso = GameScreen()
print(gso?.correctAnswers ?? 100)
}
When I print correct Answers it is still 0.
EDIT #3 I also tried this method of passing it through a segue and it is always nil. Does the fact its not working have anything to do with the fact the variable is being changed in a function? thats the only reason I can possibly think of to explain why nothing is working.
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "EndScreenSegue") {
let secondViewController = segue.destination as! EndScreen
secondViewController.recievedAnswers = correctAnswers
}
}
class EndScreen: UIViewController{
var recievedAnswers: Int!
override func viewDidLoad() {
super.viewDidLoad()
print(recievedAnswers!)
}
}
EDIT #4 Figured it out! I think.
It appears they changed prepareForSegue and it no longer works, yet xcode does not give you an error? Should another post be made about this??
Code that actually works:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EndScreenSegue"{
let secondViewController = segue.destination as! EndScreen
secondViewController.recievedAnswers = correctAnswers
}
}
You're creating a new instance of GameScreen in the viewDidLoad method of your EndScreen view controller. You need to pass the GameScreen object from your previous view controller to this one.
In your segue you're setting the correctAnswers property of your EndScreen view controller, but you're printing the value of gso?.correctAnswers. A new gso was just instantiated prior to this print statement and (I'm assuming) has a default value of 0 which is why you're getting 0 printed out.
You either need to pass the GameScreen through the segue (assuming that you're segueing from GameScreen), like so:
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "EndScreenSegue") {
let secondViewController = segue.destination as! EndScreen
correctAnswers = sender as! Int
secondViewController.gso = self
}
}
Or you can just pass the correctAnswers through the segue as you're doing but be sure to use that value, not gso?.correctAnswers
class EndScreen: UIViewController{
var correctAnswers: Int?
override func viewDidLoad() {
super.viewDidLoad()
print(correctAnswers ?? 100)
}
}
You are creating a new instance of GameScreen.
Delete this line gso = GameScreen() from viewDidLoad
For some reason it looks like prepareForSegue no longer works, yet xcode does not give an error when you use it. The correct format now is:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EndScreenSegue"{
let secondViewController = segue.destination as! EndScreen
secondViewController.recievedAnswers = correctAnswers
}
}

Prepare for segue not sending info when button is pressed

I'm learning how to pass data between controllers when a button is pressed, so I'm following this answer: Pass data through segue, But I can't make it work, I have 3 buttons and I want to know which button was pressed, so my code in HomeView is:
var buttonPressed: String?
#IBAction func newsTapped(_ sender: Any) {
buttonPressed = "news"
self.performSegue(withIdentifier: "showNext", sender: buttonPressed)
}
#IBAction func tipsTapped(_ sender: Any) {
buttonPressed = "tips"
self.performSegue(withIdentifier: "showNext", sender: buttonPressed)
}
#IBAction func otherTapped(_ sender: Any) {
buttonPressed = "other"
self.performSegue(withIdentifier: "showNext", sender: buttonPressed)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let data = buttonPressed
if let destinationViewController = segue.destination as? TableViewController {
destinationViewController.origin = data
}
And the code in destinationView (TableViewController) is:
var origin: String?
override func viewDidLoad() {
if let dataRecived = origin
switch dataRecived {
case "news":
print("News")
case "tips":
print("Tips")
case "other":
print("Other")
}
}
When I click any of the buttons, it takes me to the TableViewController, but doesn't print anything, I added the If let, since it crashed when the statement was: if let dataRecived = origin, now it never gets inside the if let statement. If I show the content of the variable (mouse over variable in xCode) it shows: ""
Any ideas why it isn't working? Not sure if it has something to do, but HomeView is a ViewController, linked to a Navigation controller that has a TableView (which is destinationView. Thanks for your help
It looks like you're getting incorrect behavior because you're running the switch statement in the viewDidLoad function which happens before the data from the previous view controller gets sent.
try adding a didSet method to the origin property to load the page like this:
class tableVC {
var origin: String? {
didSet {
if let dataRecived = origin
switch dataRecived {
case "news":
print("News")
case "tips":
print("Tips")
case "other":
print("Other")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Or you could run the switch in the the viewWillAppear method
I think the Issue you are having is in:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let data = buttonPressed
if let destinationViewController = segue.destination as? TableViewController {
destinationViewController.origin = data
}
If you have subclassed a UITableViewCotroller, you have to cast the destination View Controller to that class
`destinationViewController as? myCustomTableViewController:
if let destinationViewController = segue.destination as? myCustomTableViewController {
destinationViewController.origin = data
}

Changing label text of second ViewController upon clicking button in first ViewController

I'm new to Swift and to iOS Development. I currently have 2 ViewControllers, a button in the first and a label in the second one. I've connected the first button to the second ViewController and the transition works.
Now, when I try changing the label's text I get the error:
fatal error: unexpectedly found nil while unwrapping an Optional
value
.
Here you find my prepare function in the first ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! SecondViewController
vc.secondResultLabel.text = "Testing"
}
}
Can it be that the label in the second ViewController is somehow protected ?
Thanks for the help
You need to pass the String to the SecondViewController instead of directing setting it, as the UILabel has not been created yet.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! SecondViewController
vc.secondResultLabelText = "Testing"
}
}
And in your SecondViewController viewDidLoad method set the UILabel to be the string
var secondResultLabelText : String!
override func viewDidLoad() {
secondResultLabelText.text = secondResultLabelText
}
add a string variable in the second view controller
var labelText: String!
in second view controller also (in viewDidLoad)
self.secondResultLabel.text = self.labelText
then first view controller prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! SecondViewController
vc.labelText = "Testing"
}
}
this is because second view controller's UILabel Outlet is not being initialized yet in prepare for segue
Rikh's answer is the same, both his answer and mine are the same
Welcome aboard :)
Your problem is that your SecondViewController, and more specifically vc.secondResultLabelText is not initiated when you call prepare, so secondResultLabel is actually nil at that time.
You need to add a variable to your SecondViewController like so:
var labelText: String = ""
And then set that value instead:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! SecondViewController
vc.labelText = "Testing"
}
}
In viewWillAppear or viewDidLoad on your SecondViewController you can then use that value for your secondResultLabelText which is now ready, connected, and won't crash
secondResultLabelText.text = labelText
Hope that helps.
First take a global variable in SecondViewController... eg I took "secondViewControllerVariable". Then get the text you want to display in your SecondViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "mySegue"
{
let vc = segue.destination as! SecondViewController
vc.secondViewControllerVariable = "Your string you get in FirstViewController"
}
}
And then in your SecondViewController, in viewDidLoad method set the UILabel to be the string
var secondViewControllerVariable : String! // You have to declare this first in your SecondViewController Globally
override func viewDidLoad()
{
vc.secondResultLabelText.text = secondViewControllerVariable
}
That's it. Happy Coding.

Resources