swiftUI:how to resolve "Cannot use instance member 'store' within property initializer; property initializers run before 'self' is available"

I wat to show data from db in picker. i made it work if I use "data",now I want to change "data" to "data1",

then i get the error:"Cannot use instance member 'store' within property initializer; property initializers run before 'self' is available"

at line 09.

how to resole it?

here is my code:

Userlist.swift

import Foundation
import Foundation
import Combine

class Userlist: ObservableObject {
    @Published var mainlist: [Mainlist] = []
    
    
    init() {
        load()

    }
    
    func load() {
        let url = URL(string: "http://localhost:3000/name_v")!
        URLSession.shared.dataTask(with: url) { data, response, error in
            DispatchQueue.main.async {
                self.mainlist = try! JSONDecoder().decode([Mainlist].self, from: data!)
            }
        }.resume()
       
    }
}
struct Mainlist: Decodable{
  let name: String
}

ContentView.swift

import SwiftUI

struct ContentView: View {
    @ObservedObject var store = Userlist()
    @State  var selectedStrength = [""]
    

      //  var data: [String] = ["str1", "str2", "str3", "str4"]
        var data1: [Mainlist] = store.mainlist
    
    
    var body: some View {
      
    
        singlePicke(data: data,selectedStrength: $selectedStrength)
       
   
    }
    
}
struct singlePicke: View{
    let data: [String]
    @Binding var selectedStrength: [String]
    var body: some View{
        GeometryReader{Geometry in
            
            Picker("picker",selection:self.$selectedStrength[0]){
                ForEach(00..<self.data.count){raw in<br="">                    Text(verbatim:self.data[raw]).tag(self.data[raw])
                }
            }
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Replies

In this instance I would do away with the `data` property and just pass `store.mainlist` as the argument to your `singlePicke` view.


If that weren't an option, your only way to do this would be to implement the initializer yourself, in whatever way you'd like it to work. As a `struct` type, the synthesized initializer would take values for `store`, `selectedStrength`, and `data`, each with a default value matching the one defined in the property's declaration, with the exception of 'data', which wouldn't have a default (because as you've noticed you can't reference existing properties).


init(store: Userlist = Userlist(), selectedStrength: [String] = [""], data: [Mainlist]) { ... }


Essentially your property initializer of `store.mainlist` is setting a default parameter value of `self.store.mainlist`, which doesn't exist. Instead, you implement this initializer yourself, or rather something functionally similar:


struct ContentView: View {
    @ObservedObject var store: Userlist = Userlist()
    @State var selectedStrength = [""]

    private var data: [Mainlist]     // no initial value at declaration

    init(store: Userlist = Userlist(), selectedStrength: [String] = [""]) {
        self._store = ObservedObject(wrappedValue: store)
        self._selectedStrength = State(wrappedValue: selectedStrength)
        self.data = store.mainlist
    }

    ...
}


Note, however, that when initializing wrapped properties (i.e. @ObservedObject, @State, @Binding, etc.) you need to initialize the real value, not the 'accessor'. The actual storage for property wrapper types lives in a variable called '_name', and the 'name' property accesses '_name.wrappedValue'. In the initializer, you need to initialize the '_name' version.


If you're not going to ever pass in alternatives for the store and strength, you can use a parameterless initializer, and let the compiler handle the rest:


init() {
    // self.store and self.selectedStrength are initialized automatically here.
    self.data = self.store.mainlist
}


Again though: I don't see a compelling reason to keep a whole extra copy of the same data in this view; just pass 'store.mainlist' directly.