use init to save multiple entries to a struct (swift4) - ios

My code below uses init to save 1 entry to the struct. The problem is that it can only save 1 entry. I need to somehow make this into a array. So I am trying to use a button to submit a string to a struct where the struct can take multiple entires right now it can only take 1.
import UIKit
class ViewController: UIViewController {
#IBOutlet var c: UITextField!
#IBOutlet var a: UITextField!
#IBOutlet var label: UILabel!
#IBAction func save(_ sender: Any) {
let judo = Person.init(name: a.text ?? "", phone: Int(c.text ?? "") ?? 0)
}
struct Person : CustomStringConvertible {
var name: String
var phone: Int
static var myStruct = [String]();
var description: String {
return "\(name),\(phone)"
}}}

I understood that you want persons to be added to array on press of button
Here is the solution
var persons:[Person] = [Person]()
#IBAction func save(_ sender: Any) {
let judo = Person.init(name: a.text ?? "", phone: Int(c.text ?? "") ?? 0)
self.persons.append(judo)
}
Hope you are looking for this

Related

Adding Comment Replies to Posts as an Array of Strings in Class "Post"

I have created an app where users can generate posts that are added to a postTableView. Users can then click on any of the cells of postTableView to go to a unique view with the title and text of the post along with a commentTableView filled with user generated comments. Below the commentTableView is a textView that you can write your comment in and a button allowing you to submit your comment. I am trying to code my app so that when you press the button, the text that you wrote in the textView is appended to an array of unique comments for that post. Those comments populate the commentTableView. The following is my current flawed attempt:
Here is the Post Class:
import Foundation
class Post {
var id:String
var title: String
var text:String
var createdAt:Date
var comment: [String] = []
init(id: String, title: String,text:String, timestamp:Double, comment: [String] = []) {
self.id = id
self.title = title
self.text = text
self.createdAt = Date(timeIntervalSince1970: timestamp / 1000)
}
static func parse(_ key:String, data:[String:Any]) -> Post? {
if let title = data["text"] as? String,
let text = data["title"] as? String,
let timestamp = data["timestamp"] as? Double {
return Post(id: key, title: title, text: text, timestamp:timestamp, comment: [])
}
return nil
}
}
Here is my current view controller that you get when you click on any of the cells from the postTableView:
import Foundation
import UIKit
import Firebase
class MainTextView: UIViewController {
#IBOutlet weak var titleText: UILabel!
#IBOutlet weak var mainText: UILabel!
#IBOutlet weak var commentPlaceHolder: UILabel!
#IBOutlet weak var newCommentLabel: UITextView!
var delegate:NewPostVCDelegate?
#IBAction func postReplyButton() {
// Firebase code here
let postRef = Database.database().reference().child("posts").childByAutoId()
let postObject = [
"comment": newCommentLabel.text,
"timestamp": [".sv": "timestamp"]
] as [String : Any]
postRef.setValue(postObject, withCompletionBlock: { error, ref in
if error == nil {
self.delegate!.didUploadPost(withID: ref.key!)
self.dismiss(animated: true, completion: nil)
} else {
// Handle error
}
})
newCommentLabel.text = String()
commentPlaceHolder.isHidden = false
}
var post: Post?
// MARK: - View Controller LifeCycle
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setMain()
}
override func viewDidLoad() {
super.viewDidLoad()
newCommentLabel.delegate = self as! UITextViewDelegate
}
private func setMain() {
guard let post = self.post else {
return
}
titleText.text = post.text
mainText.text = post.title
}
func textViewDidChange(_commentView: UITextView) {
commentPlaceHolder.isHidden = !newCommentLabel.text.isEmpty
}
}
How can I fix my errors and programmatically execute my vision of populating my comment section with user for each post?
For
Class 'MainTextView' has no initializers
Replace
var delegate:NewPostVCDelegate
with
var delegate:NewPostVCDelegate?

Print appended struct (swift4)

I have three textifleds that I am using to append data into a struct. How can I print what I appended? Right now I am getting a error message.
import UIKit
class ViewController: UIViewController {
#IBOutlet var c: UITextField!
#IBOutlet var a: UITextField!
#IBOutlet var b: UITextField!
var contacts: [Person] = []
#IBAction func press(_ sender: Any) {
contacts.append(Person(name: a.text!, surname: b.text! , phone: Int(c.text!)!))
print(ViewController.Person)
}
struct Person {
var name: String
var surname: String
var phone: Int
}
}
You are trying to print the actual struct of Person. You want to print a specific instance.
You can print the whole array as:
print("contacts: \(contacts)")
If you want to print the one instance, I would suggest splitting your code a little:
#IBAction func press(_ sender: Any) {
let person = Person(name: a.text!, surname: b.text! , phone: Int(c.text!)!)
print(person)
contacts.append(person)
}
But to make the printing useful you should add the description property to your struct and make your struct conform to CustomStringConvertible.
struct Person: CustomStringConvertible {
var name: String
var surname: String
var phone: Int
var description: String {
return "Person name: \(name), surname: \(surname), phone: \(phone)"
}
}
You should also learn to safely deal with optionals. The ! operator means "crash if not nil". Your code will crash if the user types in "Hello" into the phone field.
#IBAction func press(_ sender: Any) {
if let name = a.text, let surname = b.text, let phoneStr = c.text, let phone = Int(phoneStr) {
let person = Person(name: name, surname: surname, phone: phone)
print(person)
contacts.append(person)
}
}
And also consider that a phone number is not a numeric value. Use String, not Int to store phone numbers.
I have modified your code, you can use it it will give you result what you want.
import UIKit
class ViewController: UIViewController {
#IBOutlet var c: UITextField!
#IBOutlet var a: UITextField!
#IBOutlet var b: UITextField!
var contacts: [Person] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func press(_ sender: Any) {
contacts.append(Person(name: a.text!, surname: b.text! , phone: Int(c.text!)!))
print(self.contacts.description)
}
struct Person {
var name: String
var surname: String
var phone: Int
}}
I have just made one change in print statement. As your contacts array in you view controller itself so you can directly use it by self and use function description for printing updating values of contacts.
print(ViewController.Person) is wrong
Please use:
print(contacts.last)

How To Fix: "Expression is Ambiguous".

I am trying to create an app that can help you calculate sales tax on an item. Of course the app requires multiplication But I keep encountering the error:
"Type of expression is ambiguous without more context"
Can you help me? I'm new to swift so also try to explain why I am incorrect. This is my code so far:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var Item: UITextField!
#IBOutlet weak var Tax: UITextField!
#IBOutlet weak var Answer: UITextField!
#IBAction func Calculate(_ sender: Any) {
let a = Item.text
let conversionRate = Tax
let b = Int(a!)! * conversionRate
Answer.text = ("\(b)")
}
}
Thanks!!
Your primary issue is your attempt to multiply an Int and a UITextField.
You attempt to create an Int from Item.text but you make no similar attempt to convert Tax.text to a number.
There are also many other issues with your code. You are using the ! operator too much and your app will crash as a result.
And your naming conventions need to be improved. Variables and methods should start with lowercase letters.
Here's your code as it should be written:
class ViewController: UIViewController {
#IBOutlet weak var item: UITextField!
#IBOutlet weak var tax: UITextField!
#IBOutlet weak var answer: UITextField!
#IBAction func calculate(_ sender: Any) {
if let itemStr = item.text, let taxStr = tax.text, let itemVal = Int(itemStr), let taxVal = Int(taxStr) {
let result = itemVal * texVal
answer.text = "\(result)"
} else {
answer.text = "Invalid values"
}
}
}
You're trying to multiply a variable of UITextField type with a variable of Int. Try this:
class ViewController: UIViewController {
#IBOutlet weak var Item: UITextField!
#IBOutlet weak var Tax: UITextField!
#IBOutlet weak var Answer: UITextField!
#IBAction func Calculate(_ sender: Any) {
guard let a = Int(Item.text ?? "0") else { return }
guard let conversionRate = Int(Tax.text ?? "0") else { return }
let b = a * conversionRate
Answer.text = ("\(b)")
}
}

Converting string value from text field to integer

I'm really new to Swift and I am having problems with the conversion of a string (entered in a text field) to an integer.
I'm trying to create a small calculation app (I was following a tutorial on YouTube but it's old).
My app has 3 text fields, a label (that is meant to display the result), and a button to start the calculation.
Here's the code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var valueA: UITextField!
#IBOutlet weak var valueB: UITextField!
#IBOutlet weak var valueC: UITextField!
#IBOutlet weak var result: UILabel!
#IBAction func calculateTotal(_ sender: Any) {
var a:Int? = Int(valueA.text)
var b:Int? = Int(valueB.text)
var c:Int? = Int(valueC.text)
var answer = a! * b! * c!
}
}
Try this (crash free code and you can add n number of textfield/string values as a number string):
var arrayOfTextFieldValues = [valueA.text, valueB.text, valueC.text]
#IBAction func calculateTotal(_ sender: Any) {
if let multiplication = multiplication(arrayString: arrayOfTextFieldValues) {
print("Answer = \(multiplication)")
result.text = "\(multiplication)"
}
}
// handle operations
func multiplication(arrayString: [String?]) -> Int? {
var answer:Int?
for arrayElement in arrayString {
if let stringValue = arrayElement, let intValue = Int(stringValue) {
answer = (answer ?? 1) * intValue
}
}
return answer
}

How to display answer to a greaterInt in a label using Swift?

I have the user input numbers into some textFields. Then I make some combinations out of them and then do a series of finding of finding which number is greater than the other. For example out of a and b which is greater, then out of c and d which is greater. Then out of the the two winners which is greater from that. I want my ultimate answer to be displayed in a label on a different viewController, but am having trouble with this.
I created a struct called "help" in a swift file called "PrisonerModel.swift" and want the answer to be displayed in the answer label on MatrixViewController. I believe my problem is coming up something in the process of calling the answer.
My code:
import Foundation
struct PrisonerModel {
var x: String
var y: String
var z: String
var a: String
var b: String
var c: String
var d: String
var e: String
var answer: String
}
struct help {
var f: String
func greaterInt(x: Int, _ y: Int) -> Int {
if x > y {
return x}
return y
}}
Second ViewController
class MatrixViewController: UIViewController {
#IBOutlet weak var P1CoopCoop: UILabel!
#IBOutlet weak var P2CoopCoop: UILabel!
#IBOutlet weak var P1DefCoop: UILabel!
#IBOutlet weak var P2DefCoop: UILabel!
#IBOutlet weak var P1CoopDef: UILabel!
#IBOutlet weak var P2CoopDef: UILabel!
#IBOutlet weak var P1DefDef: UILabel!
#IBOutlet weak var P2DefDef: UILabel!
#IBOutlet weak var answer1: UILabel!
var labelText1 = ""
var model: PrisonerModel?
var answer: help?
override func viewDidLoad() {
super.viewDidLoad()
P1CoopCoop.text = model?.x
P2CoopCoop.text = model?.y
P1DefCoop.text = model?.z
P2DefCoop.text = model?.a
P1CoopDef.text = model?.b
P2CoopDef.text = model?.c
P1DefDef.text = model?.d
P2DefDef.text = model?.e
answer1.text = answer?.f
Segue
prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showMatrix" {
if let matrixVC = segue.destinationViewController as? MatrixViewController {
let pm = PrisonerModel(x: Text3.text ?? "", y: Text3.text ?? "", z: Text4.text ?? "", a: Text1.text ?? "", b: Text1.text ?? "", c: Text4.text ?? "", d: Text2.text ?? "", e: Text2.text ?? "", answer: String(Int(Text1.text! + Text3.text!)) ?? "")
matrixVC.model = pm
}
}
}
It isn't clear what the "answer" should be, but some general advice is to convert your text values to integers so that you can perform appropriate mathematical operations on them.
I would implement func shouldPerformSegue(withIdentifier identifier: String,
sender: Any?) -> Bool to first validate your inputs and create your model:
struct PrisonerModel {
var x: Int
var y: Int
var z: Int
var a: Int
var b: Int
var c: Int
var d: Int
var e: Int
var answer: Int
}
var model: PrisonerModel?
override func shouldPerformSegue(withIdentifier identifier: String,
sender: Any?) -> Bool {
if let identifier == "showMatrix" {
guard let a = Int(text1.text!),
let b = Int(text1.text!),
let c = Int(text4.text!),
let d = Int(text2.text!),
let e = Int(text2.text!),
let x = Int(text3.text!),
let y = Int(text3.text!),
let z = Int(text4.text!),
let answer = Int(text1.text + text3.txt) else {
// Probably set some text in a label informing the user that their input is invalid
return false
}
self.model = PrisonerModel(x:x, y:y, z:z, a:a, b:b, c:c, d:d, e:e, answer:answe)
return true
}
}
return false
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showMatrix" {
if let matrixVC = segue.destinationViewController as? MatrixViewController,
let model = self.model {
matrixVC.model = model
}
}
}
Note I have changed the name of your text field properties to start with a lower case letter as is convention. Also your code would possibly be clearer if you had better names for your model properties than a,b,c etc.
Also the use of the force unwrap for the text properties is safe unless you have explicitly assigned nil to the property; by default a UITextField will have a string assigned to text.

Resources