UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

@State property wrapper not working in FlagImage Struct

Forums > SwiftUI

When I try using an @State property wrapper in my first struct, FlagImage, it doesn't work. Xcode gives me this error: "'FlagImage' initializer is inaccessible due to 'private' protection level" - Why is it doing this? I don't really understand the error.

I took @State off and it works just fine. Below is my code of the app that works without the property wrapper

import SwiftUI

struct FlagImage: View {
    var flag: String

    var body: some View {
        Image(flag)
            .renderingMode(.original)
            .clipShape(Capsule())
            .shadow(radius: 8)
    }
}

struct Title: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.largeTitle)
            .foregroundColor(.accentColor)
            .padding()
    }
}

extension View {
    func titleStyle() -> some View {
        modifier(Title())
    }
}

struct ContentView: View {

    @State private var showingScore = false
    @State private var scoreTitle = ""
    @State private var userScore = 0
    @State private var maxNumberOfQuestions = 8

    @State private var questionTitle = ""
    @State private var endGame = false
    @State private var currentQuestion = 1
    @State private var correctAnswer = Int.random(in: 0...2)

    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()

    var body: some View {
        ZStack {

            RadialGradient(gradient: Gradient(colors: [Color("Light Pink"), Color("Light Blue")]), center: .bottom, startRadius: 200, endRadius: 400)
                .ignoresSafeArea()

            VStack {

                Spacer()

                HStack {

                    Image(systemName: "flag.filled.and.flag.crossed").foregroundColor(.black)
                    Text("Guess the Flag")
                        .titleStyle()
                    Image(systemName: "flag.and.flag.filled.crossed").foregroundColor(.black)
                }

                VStack(spacing: 15) {

                    Text("Tap the flag of")
                        .foregroundStyle(.secondary)
                        .font(.subheadline.weight(.heavy))
                    Text(countries [correctAnswer]).font(.largeTitle.weight(.semibold))

                    ForEach(0..<3) { number in
                        Button {
                            print("tapped \(countries[number])")
                            flagTapped(number)

                        } label: {
                            FlagImage(flag: countries[number])
                        }
                    }
                }
                .frame(maxWidth:350)
                .padding(.vertical, 20)
                .background(.thinMaterial)
                .clipShape(RoundedRectangle(cornerRadius: 100))

                Spacer()
                Spacer()

                Text("Score: \(userScore)")
                    .foregroundColor(.black)
                    .font(.title.bold())
                Text("Question: \(currentQuestion)")
                    .foregroundColor(.black)
                    .font(.title.bold())

                Spacer()
            }
            .padding()
        }
        .alert(questionTitle, isPresented: $endGame) {
            Button("RESTART GAME", action: newGame)
        } message: {
            Text("Congrats! Final Score: \(userScore).")
        }
        .alert(scoreTitle, isPresented: $showingScore) {
            Button("Continue", action: askQuestion)
        } message: {
            Text("Your Score: \(userScore).")
        }
    }
    func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scoreTitle = "Correct"
            userScore += 10
        } else {
            scoreTitle = "Wrong! It's the flag of \(countries[correctAnswer])."
        }
        showingScore.toggle()
    }
    func askQuestion() {
        if currentQuestion < 8 {
            countries.shuffle()
            currentQuestion += 1
            correctAnswer = Int.random(in: 0...2)
        } else {
            endGame.toggle()
        }
    }
    func newGame() {
        if currentQuestion == 8 {
            userScore = 0
            currentQuestion = 0
            countries.shuffle()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

2      

I ran your project by copy and pasting to a new project and got no errors!

2      

As @NigelGee says, your code works. As a general rule, when asking for help you should post the non-working code for people to play around with.

Anyway, presumably your non-working code had something like this:

@State private var flag: String

That would make this line:

FlagImage(flag: countries[number])

have the exact error you reference in your post. That's because flag is marked as private.

You can fix the error by adding an initializer to FlagImage like so:

    init(flag: String) {
        self._flag = State(wrappedValue: flag)
        //this initializes the @State property wrapper with the passed-in value
    }

But as you've found, you can also fix that error by removing the @State private part. In this case, @State is not actually necessary since you don't make any changes to flag inside the FlagImage struct. @State is used when you need to change a property of a View; if you aren't changing a property, it doesn't need to be marked as @State.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.