NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: .sheet dismisses itself as soon as it opens

Forums > SwiftUI

I am trying to open a sheet with the summary of a times tables quiz for the day 35 challenge. But whenever it opens it closes immediately.

Thankyou in advance:

PlayView (This opens the sheet)

import SwiftUI

struct PlayView: View {
    @ObservedObject var variable: variables
    @State private var number1 = 8
    @State private var number2 = 2
    @State private var answer = 0
    @State private var givenAnswer = ""

    @State private var doneQuestions = 0

    @State private var showingSheet = false
    var comparableAnswer: Int{
        Int(givenAnswer) ?? 0
    }
    var body: some View {
        ZStack{
            LinearGradient(colors: [.blue, .white], startPoint: .top, endPoint: .bottom)
                .ignoresSafeArea()
            ZStack{
            VStack(spacing: 40){
                HStack{
                    Spacer()
                Text("\(variable.correct)")
                        .padding(20)
                        .background(.green)
                        .clipShape(RoundedRectangle(cornerRadius: 20))
                    Text("\(variable.wrong)")
                        .padding(20)
                        .background(.red)
                        .clipShape(RoundedRectangle(cornerRadius: 20))
                }.padding()
                Text("Question: ").font(.largeTitle)
                Text("\(number1) X \(number2)").font(.largeTitle)
                TextField("Enter Answer", text: $givenAnswer)
                    .font(.largeTitle)
                Button("Submit"){
                    if (comparableAnswer == answer){
                        variable.correct += 1
                    }else {
                        variable.wrong += 1
                    }
                    newQuestion()
                    doneQuestions += 1
                    if (doneQuestions == variable.questions){
                        variable.playing = false
                        doneQuestions = 0
                        showingSheet = true
                    }
                }.font(.largeTitle).padding(10).background(.blue).foregroundColor(.white).clipShape(Capsule())

            }
            .sheet(isPresented: $showingSheet) {
                Summaryiew(variable: variable)
            }
            .frame(width: 300, height: 440)
            .padding()
            .background(.ultraThinMaterial)
            .clipShape(RoundedRectangle(cornerRadius: 50))

            }.padding()
        }
        .onAppear(){
            newQuestion()
        }
    }
    func newQuestion() {
        number1 = variable.table
        number2 = Int.random(in: 2..<13)
        answer = number1 * number2
    }
}

struct PlayView_Previews: PreviewProvider {
    static var previews: some View {
        PlayView(variable: variables())
    }
}

SummaryView(What the sheet opens)

import SwiftUI

struct Summaryiew: View {
    @ObservedObject var variable: variables
    var body: some View {
        ZStack{
            LinearGradient(colors: [.blue,.white], startPoint: .top, endPoint: .bottom)
                .ignoresSafeArea()
            VStack(spacing: 20){
                Button("Next"){
                    variable.playing = false
                    variable.wrong = 0
                    variable.correct = 0
                }.padding().font(.largeTitle).foregroundColor(.white).background(.blue).clipShape(RoundedRectangle(cornerRadius: 20))
                Text("Well Done").font(.largeTitle).foregroundColor(.white)
                HStack{
                    Text("Correct:").font(.largeTitle)
                    Text("\(variable.correct)").padding().foregroundColor(.white).background(.green).font(.largeTitle).clipShape(RoundedRectangle(cornerRadius: 15))
                }
                HStack{
                    Text("Wrong:").font(.largeTitle)
                    Text("\(variable.wrong)").padding().foregroundColor(.white).background(.red).font(.largeTitle).clipShape(RoundedRectangle(cornerRadius: 15))
                }

            }
        }
    }
}

struct Summaryiew_Previews: PreviewProvider {
    static var previews: some View {
        Summaryiew(variable: variables())
    }
}

   

Your state value change right before showing the sheet is causing a redraw on the View, thus resetting the state Bool to false, methinks. Try decoupling the state changes you make before it, or DispatchQueue.main.async{...}'ing the Bool change to show. In short, though, your best time spent is some redesign work, and ensure that your button push's only real responsibility is to set that Bool to true to show the Sheet. That's your biggest issue - making state changes, then showing a Sheet (or anything else) right on the heels of that while the View is redraw(n / ing)

   

All of this....

Button("Submit"){
    if (comparableAnswer == answer){
        variable.correct += 1
    }else {
        variable.wrong += 1
    }
    newQuestion()
    doneQuestions += 1
    if (doneQuestions == variable.questions){
        variable.playing = false
        doneQuestions = 0
        showingSheet = true
    }
}

... is your problem.

Maybe consider making the State changes (that cause the View redraw) as the after-the-sheet-is-dismissed functionality.

.sheet(isPresented: $showingSheet) {
    // your state updates go here
} content: {
    // your sheet content goes here
}

Like... deal with all the stuff involving THIS question here and now, THEN prep, calculate scores (etc), for the View draw on the next question.

So to expand on your ideal here, ask the question, get the the answer, show the subview with parent view's data + new values without changing the old values, then on dismiss, update the old values, pluck the new question, redraw.

Doing your user-visibile View updates after the sheet goes away is perfectly fine since (in theory, not having seen your sheet content), the Sheet covers the current View (or at least obscures it enough) that the updates having later don't matter - and may make for a more cohesive workflow anyway.

$.02

(the design just needs more thought put into it, in terms of flow and how the data informs the draw)

1      

To expand... state, and all incoming information should inform the View how to draw itself, rather than being some fungible pool of bits that each view can swizzle around at a whim. If you go into SwiftUI with the mindset that "every single thing I touch will make this View draw again", you can start to see why extra-View data manipulation, and pre-View ducks-in-a-row setup becomes an early-in-the-design consideration, long before you start writing the code.

   

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

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

Reply to this topic…

You need to create an account or log in to reply.

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.