Cannot use instance member 'dateType' within property initializer; property initializers run before 'self' is available

Viewed 2909

I'm quite new to SwiftUI and can't get around this error. I'm trying to use two @State variables (isGlobal and dataType) in another array within the same initializer.

I keep getting the error: "Cannot use instance member 'dateType' within property initializer; property initializers run before 'self' is available" and "Cannot use instance member 'isGlobal' within property initializer; property initializers run before 'self' is available"

This is the code at the beginning of the view:

struct Home : View {
@State var dateType : Int
@State var isGlobal = true

@State var dailyVax = [
    
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 6))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 6))", show: true),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 5))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 5))", show: false),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 4))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 4))", show: false),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 3))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 3))", show: false),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 2))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 2))", show: false),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 1))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 1))", show: false),
    DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 0))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 0))", show: false),
]

var body: some View { ...

Here's the [DailyVaccinations] struct:

struct DailyVaccinations : Identifiable {
var id = UUID().uuidString
var day : String
var value : String
var show : Bool

}

And here's the code that actually uses the "dailyVax" array:

ForEach(dailyVax.indices,id: \.self){i in
                        
                        
                        GraphView(data: dailyVax[i], allData: dailyVax)
                            .onTapGesture {
                            
                                withAnimation{
                                    
                                    for index in 0..<dailyVax.count{
                                        dailyVax[index].show = false
                                    }
                                    dailyVax[i].show.toggle()
                                }
                                
                            }
                        
                        if dailyVax[i].value != dailyVax.last!.value {
                            Spacer(minLength: 0)
                        }
                        
                    } ...

If anyone can help me solve this issue it would be greatly appreciated! thank you

1 Answers

You are getting this error message because you are trying to access isGlobal and dateType inside of the initializer.

You can not do this when all of the values are not yet defined, hence the "before self is available" in the error message.

To fix this, code a custom initializer:

init(dateType: Int, isGlobal: Bool = true) {
        self.dateType = dateType
        self.isGlobal = isGlobal
        
        self.dailyVax = [
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 6))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 6))", show: true),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 5))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 5))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 4))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 4))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 3))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 3))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 2))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 2))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 1))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 1))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 0))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 0))", show: false)
        ]
        
// Note that all values are being given a value in the initializer (dateType, isGlobal, and dailyVax)


    }

By doing this SwiftUI knows that all values are being initialized before changing and/or using any other values provided in the initializer. I'm pretty new to SwiftUI as well, but that's my understanding of it. For more information on how initializers work and what they can do, I recommend searching on Google for more on the topic and/or visit the official Swift documentation:

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

This is how your code should look in the end:

struct Home : View {
    @State var dateType: Int
    @State var isGlobal: Bool
    
    @State var dailyVax: [DailyVaccinations]
    
    init(dateType: Int, isGlobal: Bool = true) {
        self.dateType = dateType
        self.isGlobal = isGlobal
        
        self.dailyVax = [
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 6))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 6))", show: true),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 5))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 5))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 4))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 4))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 3))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 3))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 2))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 2))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 1))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 1))", show: false),
            DailyVaccinations(day: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: false, dayCt: 0))", value: "\(showData(tabType: isGlobal, date: dateType, dataType: 4, change: true, dayCt: 0))", show: false)
        ]

    }
    
    var body: some View {
        ...
    }
    
}
Related