I have some code like the following where I want to update a string and a color through SwiftUI's binding but I get these errors:
Initializer 'init(_:)' requires that 'Binding' conform to 'StringProtocol'
Cannot convert value of type 'Binding' to expected argument type 'Color?'
import SwiftUI
struct PasswordStrengthIndicator: View {
private let segment = RoundedRectangle(cornerRadius: CGFloat(4))
@State private var segmentColor = Color.gray
@State private var hintText = ""
var body: some View {
VStack {
segment
.foregroundColor($segmentColor)
Text($hintText)
}
.onAppear(perform: onAppear)
}
func onAppear() {
segmentColor = Color.red
hintText = "Enter password!"
}
}
If I remove the $
binding indicator I get no errors but text and color does not get updated. How do I fix these issues in SwiftUI 2 without overcomplicating the code?
UPDATE:
Above code works but it does not work if the text/color change is done in a method called from a parent view, e.g.:
func onAppear() {
}
// Called from parent view.
func updateStrengthIndication() {
segmentColor = Color.red
hintText = "Enter password!"
}
CodePudding user response:
Ok an alternative would be to create an extra View Model for your PasswordStrengthIndicator
View which you could then wrap in the View Model of your parent view.
// MARK: - Parent View
class ParentViewModel: ObservableObject {
@Published var childViewModel = PasswordStrengthIndicatorViewModel()
func updateBtnDidTab() {
childViewModel.updateIndicator()
}
}
struct ContentView: View {
@StateObject var parentVM = ParentViewModel()
var body: some View {
VStack {
PasswordStrengthIndicator(
viewModel: parentVM.childViewModel
)
Button("Change", action: parentVM.updateBtnDidTab)
}
}
}
// MARK: - Child View
class PasswordStrengthIndicatorViewModel: ObservableObject {
@Published private(set) var segmentColor = Color.gray
@Published private(set) var hintText = ""
func updateIndicator() {
segmentColor = Color.green
hintText = "asdf"
}
}
struct PasswordStrengthIndicator: View {
@ObservedObject var viewModel: PasswordStrengthIndicatorViewModel
private let segment = RoundedRectangle(cornerRadius: CGFloat(4))
var body: some View {
VStack {
segment
.foregroundColor(viewModel.segmentColor)
Text(viewModel.hintText)
}
}
}
Edit:
Displaying a preview for PasswordStrengthIndicatorViewModel
:
struct PasswordStrengthIndicator_Previews: PreviewProvider {
static var previews: some View {
PasswordStrengthIndicator(
viewModel: PasswordStrengthIndicatorViewModel()
)
}
}