(Swift) Save data from UITextField into Firebase Firestore - swift

Currenty the code shown saves the String "TEST" in the Firestore database. What I need to have happen is for the text entered into the UITextField to be saved when the buttons pressed and that data be saved in the Firestore database.
For my IBAction func, I believe that it is correct but I do not know how to take the train variable and place it in my dict without getting an error.
import Foundation
import UIKit
import Firebase
import FirebaseUI
class TrainViewController: UIViewController{
#IBOutlet weak var trainField: UITextField!
#IBOutlet weak var locationField: UITextField!
#IBOutlet weak var engineField: UITextField!
#IBAction func saveButton(_ sender: UIButton) {
var train: String = trainField.text!
}
override func viewDidLoad() {
super.viewDidLoad()
trainField.delegate = self
var dict = [String:String]()
dict.updateValue("TEST", forKey: "train")
let db = Firestore.firestore()
db.collection("users").addDocument(data: dict)
}
}
extension TrainViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}

You may want to collect the string from the field in the action and then pass it to a function for saving.
class TrainViewController: UIViewController{
#IBOutlet weak var trainField: UITextField!
#IBOutlet weak var locationField: UITextField!
#IBOutlet weak var engineField: UITextField!
#IBAction func saveButton(_ sender: UIButton) {
let trainText = trainField.text!
self.saveText(theText: trainText)
}
override func viewDidLoad() {
super.viewDidLoad()
}
func saveText(theText: String) {
let db = Firestore.firestore()
let dict = ["train_text": theText]
db.collection("users").addDocument(data: dict)
}
}
Will result in the following being written to Firestore
your_firestore
users
random_doc_id
train_text: "the passed in string"
EDIT
Based on some new info, the OP would like to take the text from three text fields and write them all to a single document.
So change the button action thusly - all it does is calls our saveText function and does not pass any data.
#IBAction func saveButton(_ sender: UIButton) {
self.saveText()
}
then the saveText function
func saveText() {
let trainText = self.trainField.text!
let locationText = self.locationField.text!
let engineText = self.engineField.text!
let db = Firestore.firestore()
let dict = ["train_text": trainText,
"location_text": locationText,
"engine_text": engineText]
db.collection("users").addDocument(data: dict)
}
and the resulting Firestore looks like this
your_firestore
users
random_doc_id
train_text: "text from the train field"
location_text: "text from the location field"
engine_text: "text from the engine field"

This is fairly simple to achieve, what you need to do is declare a function that saves the data after it's entered.
The reason you aren't able to save the trainField is because when the ViewController calls viewDidLoad the button hasn't been pressed, therefor you aren't getting the text from the trainTextField.
To solve this you can do the following:
fileprivate func saveTrainWithData(text: String) {
let dictData = ["train": text] as [String:Any]
// save data to FireStore here using `dictData`
let db = Firestore.firestore()
db.collection("users").addDocument(data: dictData)
}
Now to fire this function off just call it inside of the #IBAction as shown below
#IBAction func saveButton(_ sender: UIButton) {
var train: String = trainField.text!
saveTrainWithData(text: train)
}

Related

array of image literals getting "Type of expression is ambiguous without more context" in swift 5

I am new to coding and am trying to learn Swift. I am making a simple "Rock Paper Scissors" app to practice using MVC.
I have an array (let imagesArray = [image literal, image literal, image literal]
when I have images array in the controller it works fine but when I try to move it to the model I get a "Type of expression is ambiguous without more context" error. Are image arrays not allowed in the model? my understanding is that data should be kept in the model so that's why I am trying to put it in there.
any thoughts would be much appreciated :)
struct GameBrain {
let images = [ #imageLiteral(resourceName: "rock"), #imageLiteral(resourceName: "paper"), #imageLiteral(resourceName: "scissors")]
func playGame() -> Int {
let choices = [0,1,2]
let choice = choices.randomElement()
return choice!
}
mutating func getWinner(choice: Int?) {
}
}
class ViewController: UIViewController {
var gameBrain = GameBrain()
#IBOutlet weak var imageViewLeft: UIImageView!
#IBOutlet weak var imageViewRight: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func goButton(_ sender: UIButton) {
imageViewLeft.image = images[gameBrain.playGame()]
imageViewRight.image = images[gameBrain.playGame()]
}
}
If you move images into the model you have to adjust the references
#IBAction func goButton(_ sender: UIButton) {
imageViewLeft.image = gameBrain.images[gameBrain.playGame()]
imageViewRight.image = gameBrain.images[gameBrain.playGame()]
}
Apparently the index is not needed so this is simpler
var playGame : UIImage {
return images.randomElement()!
}
and
#IBAction func goButton(_ sender: UIButton) {
imageViewLeft.image = gameBrain.playGame
imageViewRight.image = gameBrain.playGame
}

How to access a text field value and convert to double

I am working on trying to build a tip calculator using swift but am running into a multitude of problems. I have a text box where the user enters in the bill amount and then they can adjust a slider to indicate the percentage that they want to tip. I have managed to get the slider and label associated with it to work where changing the value on the slider changes the label. However, I can't figure out how to get the text field to work. I attempted to create an action for the bill amount text box being changed but no matter what I put in it, it doesn't seem like the code is ever being executed (Whenever I run the code and click in the text box, the keyboard won't go away so maybe this is part of the problem?). All that I need is to be able to access the value in the text box field inside of my action when I click the calculate button but I can't seem to even get the value to show up much less convert it to a double so I can perform calculations on it. I am super new to swift and really want to learn what I am doing wrong. I have tried multiple tutorials and similar questions on here but none of them work. I appreciate all help y'all can give.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var txtBillAmount: UITextField!
#IBOutlet weak var lblTipPercentage: UILabel!
#IBOutlet weak var sldTipPercentage: UISlider!
#IBOutlet weak var lblTipAmount: UILabel!
#IBOutlet weak var lblTotalAmount: UILabel!
var tipPercentage = 10
var billAmount = ""
#IBAction func valueChanged(sender: AnyObject) {
let currentValue = Int(sldTipPercentage.value)
lblTipPercentage.text = "\(currentValue)%"
tipPercentage = currentValue
}
#IBAction func btnCalculate(sender: AnyObject) {
lblTipAmount.text = "\(billAmount)"
}
#IBAction func txtBillAmountValueChanged(sender: AnyObject) {
}
override func viewDidLoad() {
super.viewDidLoad()
//txtBillAmount.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func btnReset(sender: UIButton) {
sldTipPercentage.value = 10
lblTipPercentage.text = "10%"
txtBillAmount.text = ""
lblTipAmount.text = "--"
lblTotalAmount.text = "--"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is a screenshot of how the UI looks
Error that I am getting
[Xcode >= 7 and Swift > 2]
Try like this
#IBAction func btnCalculate(sender: AnyObject) {
if let textValue = txtBillAmount.text {
let billAmnt = Double(textValue)
let tipAmount = (billAmnt*tipPercentage)/100
lblTipAmount.text = "\(tipAmount)"
}
}
If you are using Xcode-6 and Swift < 2 then try the following way. because String initializer for Double is only available in Swift 2 (Xcode 7). [Recommend update your Xcode]
#IBAction func btnCalculate(sender: AnyObject) {
let billAmnt = (txtBillAmount.text! as NSString).doubleValue
let tipAmount = (billAmnt*tipPercentage)/100
lblTipAmount.text = "\(tipAmount)"
}

How do I check if x is in a variable in classes within a list?

I have a list called mainframe which holds classes. I want to check before adding a new username; if newusername is in mainframe.usernames perform adding the new username in.
pretty much something like this:
import UIKit
class addNewPassword: UIViewController {
var homeVC = Home()
#IBOutlet weak var createHolderItem: UITextField!
#IBOutlet weak var createHolderUsername: UITextField!
#IBOutlet weak var createHolderPassword: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func savePasswordButton(_ sender: Any) {
let holder = Holder()
holder.item = createHolderItem.text!
holder.username = createHolderUsername.text!
holder.password = createHolderPassword.text!
}
if mainframe.contains(where: { $0.username == holder.username }) {
print("test")
}
else {
homeVC.mainframe.append(holder)
homeVC.tableView.reloadData()
navigationController?.popViewController(animated: true)
}
}
I pretty much want to run a loop, within an if statement. Or am I approaching it the wrong way?
I'm new to programming, did online tutorials and trying to write my first iOS app for my aunt.
if mainframe.usernames.contains(holder.username) {
...
Use contains :
if mainframe.usernames.contains(holder.username) {
...
}

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

swift save multiple manage objects

Having issues saving my manage objects within my code. For some reason when i place data in the first view controller everything works well. For instance
I place new categories such as "Fruits", "Dairy", "Meats". The first view controller takes the data. When I click on the specific item such as "Dairy", and put in "Milk" for items within that section. If I go back to the previous view controller and click on "Meats", I see the same data i put in under "Dairy". How do i properly manage my NSManage objects.
Here is my code below.
import UIKit
import CoreData
class HomeSpecificItemViewController: UIViewController {
var selectedItem : [Items] = []
#IBOutlet weak var itemNameTextField: UITextField!
#IBOutlet weak var brandNameTextField: UITextField!
#IBOutlet weak var caloriesTextField: UILabel!
#IBOutlet weak var priceTextField: UILabel!
#IBOutlet weak var amountTextField: UITextField!
#IBOutlet weak var threshHoldNumberField: UITextField!
#IBOutlet weak var stepper: UIStepper!
override func viewDidLoad() {
super.viewDidLoad()
stepper.wraps = true
stepper.autorepeat = true
stepper.maximumValue = 10
// Do any additional setup after loading the view.
}
#IBAction func saveButton(sender: AnyObject) {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let itemDescription = NSEntityDescription.insertNewObjectForEntityForName("Items", inManagedObjectContext: context) as! Items
itemDescription.setValue(itemNameTextField.text, forKey: "Items")
itemDescription.setValue(brandNameTextField.text, forKey: "Items")
do {
try context.save()
}catch _ {
}
/*
let request = NSFetchRequest(entityName: "Items")
let results : [AnyObject]?
do {
results = try context.executeFetchRequest(request)
}catch _ {
results = nil
}
if results != nil {
self.itemDescription = results as! [Items]
}
*/
}
#IBAction func cancelPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func increaseNumberStepper(sender: UIStepper) {
threshHoldNumberField.text = Int(sender.value).description
}
}
Do you have a specific view controller for each category? If so, what you have to do is add predicates to your more specific view controllers.
Something like:
var request = NSFetchRequest(entityName: "Food")
request.predicate = NSPredicate(format: "category == %#", "Meat")
meats = try! context.executeFetchRequest(request)
This would return an array of all Food objects whose category atribute holds the string "Meat".
I was saving my data to core data without properly declaring the manage context and without assigning the text labels to the core data object.
issue resolved!