1

The bolded line (ie var text: String...) gives a "Cannot use instance member 'numberOfDevice' within property initializer; property initializers run before 'self' is available" error. Do I need an init? If so where? Is there a different solution?

struct PairView: View {
    var theClass = BluetoothManager()   
    init() {theClass.viewDidLoad()}     

    var body: some View {
        List {
            ForEach(0..<BluetoothManager.peripheralArray.count) {   number in  //iterates thru 0 to array's count
            ConnectionView(numberOfDevice: number)      // create a ConnectionView for each number
        }
     }
  }
}

//-------

struct ConnectionView: View {
    
    var numberOfDevice: Int
    **var text: String = (BluetoothManager.peripheralArray[numberOfDevice]?.name)!**  
    // 'name' is a String property of the B.M. class's array's 'numberOfDevice index.'

    var body: some View {
        ZStack{
            RoundedRectangle(cornerRadius: 10.0).fill(Color.blue)
            Text(text).foregroundColor(Color.black)
        }
    }
}
codegeek321
  • 41
  • 1
  • 5
  • https://stackoverflow.com/questions/43550813/property-initializers-run-before-self-is-available This should help – sriram hegde Jul 04 '20 at 12:20
  • Can you give more information about your BluetoothManager and the peripheralArray, what object is stored in there? Can that object be made identifiable? – Andrew Jul 04 '20 at 12:23

3 Answers3

2

The error you encountered means you can't use the numberOfDevice variable to instantiate another variable. However, you can use the number you pass to your init method.

Try the following:

struct ConnectionView: View {
    
    var numberOfDevice: Int
    var text: String
    
    init(numberOfDevice: Int) {
        self.numberOfDevice = numberOfDevice
        self.text = (BluetoothManager.peripheralArray[numberOfDevice]?.name)!
    }
    ...
}

Note: I don't recommend force-unwrapping (!). If possible try to provide a default value.

Also, BluetoothManager looks like a type and not like an instance of a class. Make sure you access the peripheralArray property on the valid object and not on the BluetoothManager type.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
2

You can use read-only computed property with short-hand.

var text: String { 
       return (BluetoothManager.peripheralArray[numberOfDevice]?.name)!
}  
IFTTT
  • 186
  • 6
0

You can use lazy keyword for that:

lazy var text: String = (BluetoothManager.peripheralArray[numberOfDevice]?.name)!

What is lazy?

lazy means that it will postpone initialization until someone calls the variable and it will not possible if self is not initialized. So you will be sure self is ready before accessing that value.

Why?

When you call numberOfDevice, you are actually calling self.numberOfDevice, but swift is smart enough to let you not explicitly write self keyword.

The issue here is that self is not initialized yet when you are assigning a value to a variable.

So you need to make sure the variable is initialized BEFORE accessing self.

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • I had tried using lazy as recommended in many similar questions, but a lot of other errors popped up around the code, which is mainly why I asked the question. Thank you, though! – codegeek321 Jul 04 '20 at 20:29