WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Passing a boolean from one view to the next

Forums > SwiftUI

This code immediately below kinda half works, but not totally. I'm only trying to pass a boolean in one direction.

import SwiftUI

struct AddView: View {
    let newItem: Bool

    var body: some View {
        Text(String(newItem))
    }
}

struct ContentView: View {
    @State private var newItem = false
    @State private var showingAdd = false

    var body: some View {
        NavigationView {
            Form {
                Button("Add with true") {
                    newItem = true
                    showingAdd = true
                }
                Button("Add with false") {
                    newItem = false
                    showingAdd = true
                }

            }
            .sheet(isPresented: $showingAdd) {
                AddView(newItem: newItem)
            }
        }
    }
}

The code below achieves the desired result because it's using a class which both views can access, but I'm confused why the ContentView can't pass the value to the AddView using the code above.

import SwiftUI

class Test: ObservableObject {
    var newItem: Bool
    init(newItem: Bool) {
        self.newItem = newItem
    }
}

struct AddView: View {
    @ObservedObject var test: Test

    var body: some View {
        Text(String(test.newItem))
    }
}

struct ContentView: View {
    @State private var showingAdd = false
    @StateObject var test = Test(newItem: false)

    var body: some View {
        NavigationView {
            Form {
                Button("Add with true") {
                    test.newItem = true
                    showingAdd = true
                }
                Button("Add with false") {
                    test.newItem = false
                    showingAdd = true
                }
            }
            .sheet(isPresented: $showingAdd) {
                AddView(test: test)
            }
        }
    }
}

Could someone please help me?

1      

I think it's just SwiftUI getting a bit confused. If you change your code to this, it works:

NavigationView {
    Form {
        Button("Add with true") {
            newItem = true
        }
        Button("Add with false") {
            newItem = false
        }

    }
    .onChange(of: newItem) { _ in
        showingAdd = true
    }
    .sheet(isPresented: $showingAdd) {
        AddView(newItem: newItem)
    }
}

In this code, you are changing the state of newItem but pushing off the change of showingAdd until just a wee bit later, which seems to make the difference.

1      

***Yep. That works great. Much cleaner than my fix. Thanks.

Ok, so that doesn't quite work, or it doesn't achieve what I was hoping. Initially, it does but if you press the button for true, dismiss the sheet and press the button for true it doesn't launch AddView the 2nd or 3rd or nth time. It only launches when you switch back and forth between true and false.

import SwiftUI

struct AddView: View {
    let newItem: Bool

    var body: some View {
        Text(String(newItem))
    }
}

struct ContentView: View {
    @State private var showingAdd = false
    @State private var newItem = false

    var body: some View {
        NavigationView {
            Form {
                Button("Add with true") {
                    newItem = true
                }
                Button("Add with false") {
                    newItem = false
                }
            }
            .onChange(of: newItem) { _ in
                showingAdd = true
            }

            .sheet(isPresented: $showingAdd) {
                AddView(newItem: newItem)
            }
        }
    }
}

1      

Ok, so using a small modification to your suggestion, this works:

import SwiftUI

struct AddView: View {
    let newItem: Bool

    var body: some View {
        Text(String(newItem))
    }
}

struct ContentView: View {
    @State private var showingAdd = false
    @State private var newItem = false
    @State private var otherItem = 0

    var body: some View {
        NavigationView {
            Form {
                Button("Add with true") {
                    newItem = true
                    otherItem += 1
                }
                Button("Add with false") {
                    newItem = false
                    otherItem += 1
                }
            }
            .onChange(of: otherItem) { _ in
                showingAdd = true
            }

            .sheet(isPresented: $showingAdd) {
                AddView(newItem: newItem)
            }
        }
    }
}

1      

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

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.