Search code examples
initializationruntime-errorselfswift5

How to fix "cannot use instance member 'textField_1' within property initializer; property initializers run before 'self' is available"?


My compiler doesn't show any problems but at runtime, I get an unknown error. I'm trying to place textField string input into a double array. Not sure what is wrong can somebody please explain what I'm doing wrong.

Haven't really tried anything but I think I have to use lazy syntax somehow.

import UIKit
class ViewController: UIViewController {
//  Outlets
//  textFields
@IBOutlet weak var textField_1: UITextField!
 @IBOutlet weak var textField_2: UITextField!
 @IBOutlet weak var textField_3: UITextField!
 @IBOutlet weak var textField_4: UITextField!
 @IBOutlet weak var textField_5: UITextField!

//  labels  
@IBOutlet weak var label_1: UILabel!
@IBOutlet weak var label_2: UILabel!
@IBOutlet weak var label_3: UILabel!
@IBOutlet weak var label_4: UILabel!
@IBOutlet weak var label5: UILabel!
//  Variables
var input : String = "0";
var a = 0
var age = "9.5"

override func viewDidLoad() {
    super.viewDidLoad()

    //   Do any additional setup after loading the view.
}
var numbers : [Double] = [90, 0, 0, 0, 0];  // where textfields will be converted to double
var userinput : [String?] = [textField_1.text, textField_2.text, textField_3.text, textField_4.text, textField_5.text]!; // textField storage

//  Button
@IBAction func button ()
{
    //   loop inserts userinput into numbers array
    while (a < 3) {
        numbers.insert(convert_to_double(input1: userinput[a]!) ,at: a)// inserts userinput after
        a += 1 // stops loop and changes array index
    }
}
//   converts strings to double
func convert_to_double(input1: String) -> Double
{
    let input0 : Double? = Double(input1);
  return input0!
}
}

:0: error: cannot use instance member 'textField_1' within property initializer; property initializers run before 'self' is availableenter image description here


Solution

  • You are trying to access the user's input with an index value. Creating an array of text input values has two problems:

    1. In your case, you can't create this array with a property initializer because self is not available until after the class has been fully initialized.
    2. Creating an array of the user inputs will be static and won't show the latest values of the UITextFields if the user updates one before pressing the button.

    You can handle this in one of two ways.


    Use a computed property:

    If you turn userinput into a computed property, then it will always return an array with the latest values:

    var userinput : [String?] { return [textField_1.text, textField_2.text, textField_3.text, textField_4.text, textField_5.text] }
    

    The downside is that every access of userinput will recreate this array which is a bit inefficient, but it ensures the array contains the latest values. You can assign this to a local variable at the top of button to avoid recreating the array in the loop:

    @IBAction func button ()
    {
        let userinput = self.userinput
    
        //   loop inserts userinput into numbers array
        while (a < 3) {
            numbers.insert(convert_to_double(input1: userinput[a]!) ,at: a)// inserts userinput after
            a += 1 // stops loop and changes array index
        }
    }
    

    Create a lazy var of the UITextFields:

    Create a lazy array of the textFields. This array will be created the first time it is accessed, but since it contains objects, you will always have access to the latest input values from the user.

    lazy var textFields = [textField_1!, textField_2!, textField_3!, textField_4!, textField_5!]
    

    and then change your button loop to use textFields[a].text! instead of userinput[a]!:

    @IBAction func button ()
    {
        //   loop inserts userinput into numbers array
        while (a < 3) {
            numbers.insert(convert_to_double(input1: textFields[a].text!) ,at: a)// inserts userinput after
            a += 1 // stops loop and changes array index
        }
    }