History
Loading...
Loading...
September 3, 2025
onChange(of:) with TextField to format user input in real-time. For phone numbers, add let formatted = value.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression) to strip non-digits, then apply formatting logic to display as (XXX) XXX-XXXX while typing.This approach encapsulates validation styling and error display logic into a reusable ViewModifier, keeping your view code clean while providing consistent validation UI across your app.
struct ValidationModifier: ViewModifier {
let isValid: Bool
let errorMessage: String
func body(content: Content) -> some View {
VStack(alignment: .leading, spacing: 4) {
content
.textFieldStyle(.roundedBorder)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(isValid ? Color.clear : Color.red, lineWidth: 1)
)
if !isValid {
Text(errorMessage)
.font(.caption)
.foregroundColor(.red)
.transition(.opacity)
}
}
.animation(.easeInOut(duration: 0.2), value: isValid)
}
}
extension View {
func validation(isValid: Bool, error: String) -> some View {
modifier(ValidationModifier(isValid: isValid, errorMessage: error))
}
}Separating validation presentation from business logic improves code maintainability, enables consistent UI patterns, and makes testing easier by isolating concerns. The modifier can be applied to any input field with different validation rules.