Am o vedere l-a creat printr-o buclă ForEach care are nevoie pentru a lua o variabilă conta în ForEach sine, adică am nevoie de aplicația pentru a reacționa la o dinamică a număra și de a schimba UI accoridngly.
Aici este punctul de vedere am încercat să modifice:
struct AnimatedTabSelector: View {
let buttonDimensions: CGFloat
@ObservedObject var tabBarViewModel: TabBarViewModel
var body: some View {
HStack {
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.red)
ForEach(1..<tabBarViewModel.activeFormIndex + 1) { _ in
Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
.background(Color.blue)
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.green)
}
Circle().frame(
width: buttonDimensions,
height: buttonDimensions)
.foregroundColor(
tabBarViewModel.activeForm.loginFormViewModel.colorScheme
)
ForEach(1..<tabBarViewModel.loginForms.count - tabBarViewModel.activeFormIndex) { _ in
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.red)
Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
.background(Color.blue)
}
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.gray)
}
}
}
Și viewModel observ:
class TabBarViewModel: ObservableObject, TabBarCompatible {
var loginForms: [LoginForm]
@Published var activeForm: LoginForm
@Published var activeFormIndex = 0
private var cancellables = Set<AnyCancellable>()
init(loginForms: [LoginForm]) {
self.loginForms = loginForms
self.activeForm = loginForms[0] /// First form is always active to begin
setUpPublisher()
}
func setUpPublisher() {
for i in 0..<loginForms.count {
loginForms[i].loginFormViewModel.$isActive.sink { isActive in
if isActive {
self.activeForm = self.loginForms[i]
self.activeFormIndex = i
}
}
.store(in: &cancellables)
}
}
}
Și în cele din urmă loginFormViewModel:
class LoginFormViewModel: ObservableObject {
@Published var isActive: Bool
let name: String
let icon: Image
let colorScheme: Color
init(isActive: Bool = false, name: String, icon: Image, colorScheme: Color) {
self.isActive = isActive
self.name = name
self.icon = icon
self.colorScheme = colorScheme
}
}
Practic, un buton de pe formularul de autentificare se stabilește sale viewModel e isActive proprietate la true. Ne asculta pentru acest lucru în TabBarViewModel și setați activeFormIndex în mod corespunzător. Acest indice este apoi utilizat în buclă ForEach. În esență, în funcție de indicele selectat, am nevoie pentru a genera mai mult sau mai puțin distanțiere în AnimatedTabSelector vedere.
Cu toate acestea, deși activeIndex variabilă este actualizat în mod corect, ForEach nu pare să reacționeze.
Update:
La AnimatedTabSelector este declarat ca făcând parte din această vedere de ansamblu:
struct TabIconsView: View {
struct Constants {
static let buttonDimensions: CGFloat = 50
static let buttonIconSize: CGFloat = 25
static let activeButtonColot = Color.white
static let disabledButtonColor = Color.init(white: 0.8)
struct Animation {
static let stiffness: CGFloat = 330
static let damping: CGFloat = 22
static let velocity: CGFloat = 7
}
}
@ObservedObject var tabBarViewModel: TabBarViewModel
var body: some View {
ZStack {
AnimatedTabSelector(
buttonDimensions: Constants.buttonDimensions,
tabBarViewModel: tabBarViewModel)
HStack {
Spacer()
ForEach(tabBarViewModel.loginForms) { loginForm in
Button(action: {
loginForm.loginFormViewModel.isActive = true
}) {
loginForm.loginFormViewModel.icon
.font(.system(size: Constants.buttonIconSize))
.foregroundColor(
tabBarViewModel.activeForm.id == loginForm.id ? Constants.activeButtonColot : Constants.disabledButtonColor
)
}
.frame(width: Constants.buttonDimensions, height: Constants.buttonDimensions)
Spacer()
}
}
}
.animation(Animation.interpolatingSpring(
stiffness: Constants.Animation.stiffness,
damping: Constants.Animation.damping,
initialVelocity: Constants.Animation.velocity)
)
}
}
UPDATE:
Am încercat o altă cale prin adăugarea unui alt publicat la AnimatedTabSelector în sine pentru a verifica faptul că valorile sunt într-adevăr în curs de actualizare în mod corespunzător. Astfel, la sfârșitul HStack din acest punct de vedere, am adăugat:
.onAppear {
tabBarViewModel.$activeFormIndex.sink { index in
self.preCircleSpacers = index + 1
self.postCircleSpacers = tabBarViewModel.loginForms.count - index
}
.store(in: &cancellables)
}
Și, desigur, am adăugat următoarele variabile la acest punct de vedere:
@State var preCircleSpacers = 1
@State var postCircleSpacers = 6
@State var cancellables = Set<AnyCancellable>()
Apoi, în buclele ForEach am schimbat la:
ForEach(1..<preCircleSpacers)
și
ForEach(1..<postCircleSpacers)
respectiv.
Am adăugat un punct de pauză în noua persoana declarația și este într-adevăr a fi la curent cu cele așteptat cifre. Dar punctul de vedere este încă nu reușesc să reflecte schimbările în valorile