How can I set a label's value equal to another without an action? - ios

I am currently working on an iOS application (Swift) in Xcode for my work study position at school. To highlight the background of the portion mentioned in this question: The user goes through a series of pages to basically grade the student on their performance through nursing simulations. I need there to be an extra tab where the user can verify the grading that has been entered just simply by showing the number of things they selected that were done in the scenario.
Basically I have a tabbed view controller with three tabs. The first tab has switches the user can turn on or off to add or subtract to a variable, "WASH". The second tab is the same but it adds/subtracts to a variable, "ID". The third tab is to confirm the values. So if the student does 2/3 for Washing their hands and 4/5 of checking the patient's ID, it should be viewed here.
here is basically the code I have for every switch
#IBOutlet weak var IDTOTAL: UILabel!
#IBOutlet weak var CHECKID1: UISwitch!
#IBAction func ID1(_ sender: UISwitch) {
if(CHECKID1.isOn) {
ID = ID + 1
total = total + 1
IDTOTAL.text = String(ID)
}
else {
ID = ID - 1
total = total - 1
IDTOTAL.text = String(ID)
}
}
Please note that the variables ID and total are global variables. Currently, IDTOTAL is on the same view controller as the switch and this works fine. I tried to add another label on the confirm view controller called "IDTOTAL2" and tried setting it to a value with "IDTOTAL2.text = String(ID)" but this throws an error.
How do I go about making the label on the last page update its value without requiring the user to push a button to initiate an action?
EDIT: Please refer to this picture to see the error I am getting.

You can update your labels in the viewDidAppear function of your third tab, since it gets triggered every time you switch from another tab to this one. Simply add:
override func viewDidAppear(_ animated: Bool) {
//update your labels here
}

Related

Adding a new array does not update my total array count in Swift Xcode

Problem: Initially my count is correct, however, adding a new array does not update my total array count label.
I have a View Controller (VC) that shows a label with a count of total arrays.
I have a Table View Controller (TVC) that arrays are added or deleted from.
I have a separate struct file to hold the arrays.
The label populates with the correct number of arrays when I run it. However, adding a new array item (via TVC) in the simulator does not update the label on the VC.
Questions:
Should I put the count in a function in VC? It is currently in the viewDidLoad()
Should I then call the function in TVC when adding or deleting an array?
If 2 is yes then do I reference the function in VTC? Would it simply be
updateCount() or do I have to reference the VC controller e.g.
ViewController.updateCount()
I have tried both ways but it does not seem to work, if I can get confirmation that would be great then I can make it work.
Thank you in Advance
My suggestion is bad but it works.
The easiest answer is use static variable, but it will cost memory phone. example code:
import Foundation
import UIKit
class VC: UIViewController {
static var count = 0
let label: UILabel = UILabel()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
label.text = String(VC.count)
}
}
class TVC: UITableViewController {
func updateCount() {
VC.count = VC.count + 1
}
}
Whenever function updateCount() called in TVC, and go back to VC class it will update the count.
My other suggestion is use MVVM pattern that sending VCViewModel as parameter to TVC. and update count in VCViewModel.
Other suggestion is use delegate pattern.
If you do something like this:
var x = 0
var y = x
x = 7
print(y) //y is still 0
You need to update the count whenever you change the amount of arrays. To call a view controller's function from another view controller, you need to use a protocol. I suggest you research how to make protocols in swift - I would help you but it's hard without being able to see the code.

Xcode 10, Swift 4 - How do I transfer data across multiple view controllers? [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 3 years ago.
I am currently working on an app and have problems with posting events.
I collect data in a sequence of several views (7 screens) and would like to store the data finally at once (or show all the data in the final view).
These data are, for example, location info, user info, event image, comments, event category, ...
I know how to store the data in the database/storage (firebase) if I collect the data in one or two views.
But in my use case I have seven views and I could not find any elegant method.
What's the best way to do that with Xcode 10?
You can use struct as below code. Make all required variable for all screen in this struct (like string, image etc..). And you can access this from any ViewController.
struct InputDetails {
static var details: InputDetails = InputDetails()
var city: String = ""
var lat: String = ""
var long: String = ""
}
Now to add value in this
InputDetails.details.city = textfiels.text
Now to access first screen value in last screen
print(InputDetails.details.city)
And once your API call or above struct usage is over, make sure to reset all details like below.
InputDetails.details = InputDetails()
There are several ways for passing data between View Controllers. For example you could use an instance property or a segue or the delegation method.
I recommend you study this article which paints a complete picture of the different methods and how to apply them:
How To: Pass Data Between View Controllers In Swift
Edit:
Upon examining the picture in your question I figured that using a segue would be the most appropriate solution here. As it seems from the picture you enter data in one View Controller, pass that onto the second View Controller and finally you upload all the data to Firebase.
I assume that you use storyboards (if not then consult the link above for other methods.) In this example below you will pass a string from one VC to another.
Step 1:
Add a segue between two view controllers. Storyboard -> press ctrl and click on VC one and drag your mouse -> you will see a blue arrow, drag that to VC two and release -> select manual segue: show -> click on the segue and give it an identifier
Step 2:
In VC two, make a string variable:
class SecondViewController: UIViewController {
var stringToPass: String = ""
override func viewDidLoad() {
super.viewDidLoad()
print(stringToPass)
}
Step 3:
In VC one, enter the following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? SecondViewController {
vc.stringToPass = "This is the string we pass between two VC"
}
}
Step 4:
Then whenever you want to go to the SecondViewController perform the segue like this:
performSegue(withIdentifier: "identifierYouEntered", sender: self)

Observing the changes to Object Swift 4

I have Swift object with about 20 Properties. In the app, there is a screen to get the user input and create the above swift object from the user entered value. Right now, if the user clicks the back button, all the user entered data will lose. So I want to alert the user to save the details if he/she has made any changes. How do we identify if the user has made any changes to the properties. Is it possible to use KVO in this case as we have too many properties?
What you need is a data model to hold the information in that particular screen, and then compare it with the original data when leaving the screen.
For the sake of simplicity, let's assume your screen has 2 text fields. One holds a name and another the age of a person.
struct Person: Equatable {
var name: String
var age: Int
}
When you first open this screen, the model will have the default values. Create a copy of this model and whenever the user makes any changes to the values on the screen, update the copy.
class YourViewController: UIViewController {
// Populate these 2 values when creating your view controller
var person: Person!
var personCopy: Person!
.
.
.
// You need to add this target to your text fields
#objc func textFieldDidChange(_ textField: UITextField) {
switch textField {
case personTextField:
personCopy.name = personTextField.text!
case ageTextField:
personCopy.age = Int(ageTextField.text!)!
default:
// Handle other text fields here or write separate cases for them
}
func dismissView() {
if person == personCopy {
// Dismiss your view
} else {
// Show alert
}
}
}
If the user presses the back button, all you need to do is compare these 2 models and check if they are the same. If they are the same, you can go back, if not, prompt an alert asking the user to save changes or discard.
I think KVO would be overkill here. Use KVO only for distant objects in your app.
Here you have the UITextFields in your viewController and you must have reference to the user object anyway.
Easier is: On the back button press you would check all text properties of your UITextField objects to the (existing) values of your user object. If one of them has changed then present the alert.

Dynamic Label Titles

I have an app I am working on where it shows a balance for users that changes. I would like to display these values as they change and the only way I know how to do that would be with a button. But the values often change on a different view controller so I was wondering if I can set labels equal to a variable that update along with those variables.
Since the values change outside of the view controllers with the labels, the normal way I change labels, using a button, does not apply.
Thanks in advance!
As a general solution, you could achieve this by declaring a property observer in your view controller, example:
class ViewController: UIViewController {
var updatedData = "" {
didSet {
lblData.text = "Data: \(updatedData)"
}
}
#IBOutlet weak var lblData: UILabel!
}
At this point, each time updatedData value is edited, the lblData label text will be updated.
Note that there is also willSet option which is called just before the value is stored, for more information, you could check Swift Properties Documentation - Property Observers.

A UIButton is pressed in 1 VC and I need it to save the buttons title to a label in a different view controller not directly segued to each other

In the initial set up of my app I need the user to chose a genre type. i have it set up such that the user selects from a list of UIButtons which are all different genre types. I need this genre selection to save to the users profile. The next view controller is the same set up as the genreVC but asking for instrument instead of genre. The next segue from here is to view controller 3 the usersVC profile and it should have saved which two buttons were selected on the previous two VC's by updating a label. I have tagged each button with a number and have tried next to everything.
How do I save which button has been pressed on a different view controller to the users profile and update the label on the users profile to the name of the button pressed?
I am using each button individually and have them tagged as such as seen here:
#IBAction func popGenreButton(sender: UIButton) {
if(sender.tag == 6){
print("Pop genre selected")
}
}
#IBAction func altGenreButton(sender: UIButton) {
if(sender.tag == 7){
print("Alternative genre selected")
}
}
#IBAction func electronicGenreButton(sender: UIButton) {
if(sender.tag == 8){
print("Electronic genre selected")
}
}
I also tried adding each button into genreSelection as shown below that didn't work so I stuck with the individual buttons above.
#IBAction func genreSelectionButton(sender: UIButton) {
print(sender.titleLabel!.text!)
genreResult.text = genreString + " genre has been saved to your profile"
}
I also created a nib with myModalDelegate and protocol and nope.
I thought maybe I could create a genre array and when a certain button is selected it calls a certain item from the array and updates that item to the label but I was unsure how to go about this too.
I am using Xcode 7 and Swift 2.0 and Parse as my cloud server.
As you can see I have a lot to learn yet with Swift. I have been searching how to do this for the past week and can't figure it out. I am a 'lot' out of my depth but want to figure it out, if anyone can help that would be great!
A simple solution would be something like creating a global store for those values
i.e.
struct Choices {
static var genre: String?
static var instruments: String?
}
then you could in your different view controllers write and read from it by simply
Choices.instrument = "trumpet"
or
label.text = Choices.genre
A prettier solution would be to create a similar class as the previous struct but not have the variables static. You could then pass it along and fill up with the values from each VC and use the values in the last VC where you are setting the label text

Resources