I am rendering multiple cards that are swipeable. I have a variable ‘percentage’ which increases a progress bar at the top of the screen. When a card is swiped to the right I want the bar to increase but the variable is out of scope. XCode doesn’t support global scoped states so I’m a bit confused as to what to do here. I have a very simplified version of the code below.
import Photos
import SwiftUI
struct ContentView: View {
// WANT TO ACCESS THIS STATE
@State var percent: CGFloat = 0
var body: some View {
ZStack{
ForEach(imageObjectGroup){ card in
CardView(card: card).padding(8)
}
}.zIndex(1.0)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
//Card Structure
struct CardView: View{
@State var card: ImageObject
DragGesture().onChanged { value in
card.x = value.translation.width
card.y = value.translation.height
card.degree = 7 * (value.translation.width > 0 ? 1 : -1)
}
//When user stops dragging
.onEnded { value in
withAnimation(.interpolatingSpring(mass: 1.0, stiffness: 50, damping: 8, initialVelocity: 0)){
switch value.translation.width {
case 0...100:
card.x = 0; card.degree = 0; card.y = 0
// Keep
case let x where x > 100:
card.x = 800;
case (-100)...(-1):
card.x = 0; card.degree = 0; card.y = 0;
// Delete
case let x where x < -100:
card.x = -200; card.degree = -12
//WANT TO INCREMENT HERE
percentage++
default: card.x = 0; card.y = 0
}
}
}
}
2
Answers
Because you’re going to have multiple cards, it doesn’t make sense to have a single
@State var percent: CGFloat = 0
property insideContentView
that’s tied to all the cards. Instead, you wantImageObject
to have apercent
property, so that you can set eachCard
‘spercent
independently.Then, use a
@Binding
insideCardView
– this syncs all changes inpercent
to the originalimageObjectGroup
array.You can pass variable as a
@Binding
to your card, but in terms of architecture it’s not a good solution: card shouldn’t know about progress, it’s not here field of interest.Your card should notify parent that it were swiped. So I suggest you adding a block, which card will call, and then your container view you’ll increase the
progress
.Also it looks like you’re storing information about card position and rotation inside
ImageObject
. This is not very good too: you’re mixing model with view state. Most probably you don’t need this valuesImageObject
out of this view, so I suggest moving them directly to the view.