Is it possible to depend on multiple conditions in SwiftUI? For example to show a sheet:
.sheet(isPresented: $stateA && $stateB, content: { ... }) // this is not working
Or is a different approach known?
"I can only show you the door..." (c) Morpheus
Today is a day of overloaded operators :^) - previous was here, here is for your case (tested with Xcode 11.3+)
extension Binding where Value == Bool {
static func &&(_ lhs: Binding<Bool>, _ rhs: Binding<Bool>) -> Binding<Bool> {
return Binding<Bool>( get: { lhs.wrappedValue && rhs.wrappedValue },
set: {_ in })
}
}
struct TestCustomBinding: View {
@State private var isFirst = true
@State private var isSecond = false
var body: some View {
VStack {
Button("TestIt") {
self.isSecond = true
}
.sheet(isPresented: $isFirst && $isSecond) {
Button("CloseMe") {
// sheet MUST be closed explicitly via one of states !
self.isSecond = false
}
}
}
}
}
no, it is not possible! isPresented accept Binding, that means the state is updated if sheet will be dismissed. Which of stateA, stateB have to be changed? or both of them? Even though someone will try to define && operator where left and right side is Binding, that is very bad idea. Don't try to do it!
Move the logic to your model, better outside of any View.
UPDATE (for Asperi)
this is valid code (with your extension)
struct ContentView: View {
@State private var isFirst = true
@State private var isSecond = false
var body: some View {
VStack {
Button("TestIt") {
self.isSecond = true
}
.sheet(isPresented: $isFirst && $isSecond) {
Text("A")
}
}
}
}
Try it! Pressing TestIt will open the sheet. There is no Button to "go back", but you can dismiss it with well known gesture. And try to press TestIt again ...
It is possible to get different conditions from a variable.
struct ChangingButton: View {
var text: String
var onButton: String
var offButton: String
var changeButton: Bool
var buttonCondition: String {
if isOn {
return isOnImage
} else {
return isOffImage
}
}
var body: some View {
Button(action: {
action()
}
, label: {
VStack {
Image(systemName: buttonCondition)
Text(text)
}
})
}
}
struct ChangingButton_Previews: PreviewProvider {
static var previews: some View {
ChangingButton(text: "My Button", onButton: "on", offButton: "off", changeButton: true, action: {
}).background(Color.black)
}