-1

Im stuck on this part of my code, I'm trying to get an average % from the numbers entered into my Textfields. I'm very new at this and would appreciate it if someone can help out and tell me where I'm going wrong and point me in the right direction.

enter image description here

class ingredientViewController: UIViewController, UITextFieldDelegate {
   @IBOutlet var abvTextFields: [UITextField]!

   @IBOutlet var AbvTotal: UILabel!

   override func viewDidLoad() {
      super.viewDidLoad()

      AbvTotal.layer.cornerRadius = 8.0

   }

   func abvList(abvTextFields:Int...) -> Float {

     let abv1 = Float(abvTextFields.reduce(0,+))
     let abv2 = Float(abvTextFields.count)

     let abv3 = abv1 / abv2

     return abv3
  }
Rohit Parihar
  • 352
  • 1
  • 7
  • 14
Glenwing
  • 1
  • 1
  • 2
  • @IBOutlet var abvTextFields: [UITextField]! , this is way too wrong. You can not create outlets like this . This is how you create an array of outlets -> https://stackoverflow.com/a/32165366/8374890 – Keshu R. Nov 27 '19 at 11:14
  • @KeshuRai You can't know if abvtextFields is wrogn or not. It could be an Outlet Collection that has been created perfectly correctly. The handling of it's contents however could be improved... – flanker Nov 27 '19 at 11:26
  • the @IBOutlet var abvTextFields: [UITextField]! has 12 textfields, I thought it would cleaner doing it like this. I will try adding them individually and see how that goes, but the problem as far as I can tell is this "func abvList(abvTextFields:Int...) -> Float {". Is there another way of doing this? Ive been trying to fix this for hours now – Glenwing Nov 27 '19 at 11:39

1 Answers1

0

Assuming abvTextFields is a valid outlet collection of text fields their content will be strings, therefore trying to sum them using reduce(0,+) won't work. You will need to convert them to Ints first:

let sum = abvTextFields.compactMap({Int($0.text ?? "")}).reduce(0,+)
let validNumbers = abvTextFields.compactMap({Int($0.text ?? "")}).count
let average = sum / validNumbers

The above handles the text fields being empty by nil coalescing an empty string for their content, and then tries to convert the string to an Int. If the string isn't numeric converting to an Int will return nil, so compactMap is used to drop these cases.

It would be possible to do all the conversion within a complex reduce block, but this demonstrates the steps more clearly.

EDIT Note the comment below. Just use Int($0.text!) without the nil coalescing.

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
flanker
  • 3,840
  • 1
  • 12
  • 20
  • `UITextfield` `text` property default value is an empty string. It will **never** return `nil` even if you assign `nil` just before accessing its value. Therefore the use of nil coalescing operator in this case is pointless. You can simply force unwrap the text property. `Int($0.text!)` – Leo Dabus Nov 27 '19 at 12:01
  • 1
    I thought that felt strange when typing it Thanks for the catch. – flanker Nov 27 '19 at 12:13
  • There is some syntax errors in your text. You should test your code in playground before posting it. – Leo Dabus Nov 27 '19 at 12:15
  • I think has set me on the right path, here is what I have come up with, it's close to what I am after, just a little tweaking left to do. func abvList() { let abv1 = Float(abvTextFields.compactMap({Float($0.text ?? "")}).reduce(0,+)) let abv2 = Float(abvTextFields.count) let abv3 = abv1 / abv2 let vol1 = Float(volumeTextFields.compactMap({Float($0.text ?? "")}).reduce(0,+)) let abvmulti = abv3 / vol1 let abvmulti2 = abvmulti * 100 Any more insight would be appreciated, but thanks so much – Glenwing Nov 27 '19 at 12:16
  • @LeoDabus, yes, usually I would, but on the move at the moment without Xcode. – flanker Nov 27 '19 at 12:18
  • sorry its a bit of jumbled mess on here – Glenwing Nov 27 '19 at 12:18