Reputation: 9409
My app has paid features. I have a Toggle that the user can switch. If the user has not paid, then when the user tries to toggle the Toggle a sheet should be brought up (and the toggle should not be activated). If the user has paid, then the toggle can be toggled on and off without problems.
I can't understand how a simple struct (PaidFeature
) can have access to an observable object (Model
). How do I code that in SwiftUI?
class Model: ObservableObject {
@Published var hasUserPaid: Bool = false
}
struct PaidFeature {
var isEnabled = false
}
struct ContentView: View {
@State private var feature = PaidFeature()
@EnvironmentObject var model: Model
var body: some View {
Toggle(isOn: self.$feature.isEnabled) {
Text("Hello, World!")
}
}
}
Upvotes: 1
Views: 2097
Reputation: 71
You can use condition in body View
if self.model.hasUserPaid == true {
Toggle(isOn: self.$feature.isEnabled)) {
Text("Hello, World!")
}
} else {
Toggle(isOn: .constant({default Bool})) {
Text("Hello, World!")
}
}
Upvotes: 1
Reputation: 2104
Using Xcode 12, you can listen for changes of the toggle button using .onChange
modifier, and whenever user toggles the button, you can toggle it back to the last state, and instead show a purchase this
sheet if the user is not a premium user.
.onChange(self.feature.isEnabled) { isEnabled in
if isEnabled && shouldShowPurchaseSheet {
// toggle back if you want the button to go to the inactive state
// show the sheet
}
}
Upvotes: 2
Reputation: 257493
I assume it should be as
var body: some View {
Toggle(isOn: self.$feature.isEnabled) {
Text("Hello, World!")
}
.disabled(!model.hasUserPaid) // << here !!
}
Update: demo of alternate variant with showing sheet. Tested with Xcode 12 / iOS 14
For simplicity all of demo all states are kept in view
struct DemoView: View {
@State private var feature = false
@State private var paid = false
@State private var showPurchase = false
var body: some View {
Toggle(isOn: $feature) {
Text("Hello, World!")
}
.allowsHitTesting(paid)
.contentShape(Rectangle())
.simultaneousGesture(TapGesture().onEnded {
if !self.paid {
self.showPurchase = true
}
})
.sheet(isPresented: $showPurchase) {
Text("Purchase this")
.onDisappear {
self.paid = true
}
}
}
}
Upvotes: 1
Reputation: 16341
You could add a disabled
modifier to the Toggle
.
struct ContentView: View {
@State private var feature = PaidFeature()
@EnvironmentObject var model: Model
var body: some View {
Toggle(isOn: self.$feature.isEnabled) {
Text("Hello, World!")
}.disabled(!model.hasUserPaid)
}
}
Upvotes: 1