
A friend of mine once built a simple iOS login screen, thinking little of what could go wrong. Two weeks later, a test user tried pasting a long string of script tags into the username field. The app crashed.
That was all it took for us to realize input validation and data sanitization are not extras, they’re habits every developer, ourselves included, need to internalize. Especially in SwiftUI and UIKit projects, where speed often tempts us to skip the boring details.
Key Takeaways
- Regular validation and sanitization prevent attacks and keep data clean.
- Immediate UI feedback helps users fix mistakes without frustration.
- SwiftUI and UIKit offer practical tools for secure, user-friendly forms.
Core Techniques for Validation and Sanitization
We tend to think of input validation as a filter, a way to let the good data through and keep the bad out. Data sanitization, on the other hand, is our second net, cleaning up anything that slips by the first. In practice, we use both, and often at several points in our app flows. [1]
Input Validation Fundamentals
Input validation asks: “Does this data follow the rules I expect?” We set these rules using:
- Length checks (for example: username is 3–20 characters)
- Allowed character sets (letters, numbers, maybe underscores)
- Specific formats (like an email address)
We have found regular expressions especially useful for these jobs. The pattern ^[A-Za-z0-9_]{3,20}$ only allows letters, numbers, and underscores, between 3 and 20 characters. If user input doesn’t match, we reject or flag it.
Here’s what that looks like in Swift:
if let _ = input.range(of: “^[A-Za-z0-9_]{3,20}$”, options: .regularExpression) {
// Valid input
} else {
// Invalid input
}
Pattern Matching with Regular Expressions
Regular expressions (regex) are our bread and butter for format checks. They let us:
- Enforce email formats: [A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}
- Limit phone numbers to digits and dashes
- Block unwanted symbols in names
We use them both in Swift (with NSRegularExpression) and in our own validator classes.
Constraints and Format Checks
Some data needs more than a pattern. For instance, dates must be real (no February 30), and ages must be within a sensible range. We often check:
- Minimum and maximum values (e.g., age between 13 and 120)
- Specific choices (gender: “male”, “female”, “other”)
- Unique requirements (no repeated characters, etc.)
In Swift, we use simple if statements or custom validator functions for these.
Data Sanitization Methods
Sanitization is about cleaning, not just checking. Even after validation, we assume someone might try to sneak in something dangerous or weird.
Removing Harmful Characters
We strip out or reject:
- HTML tags (to prevent XSS)
- Control characters (like newlines or tabs)
- Invisible unicode, especially when tied to weak spots in iOS transport security that expose unexpected payloads.
A practical Swift example for trimming whitespace and removing control characters:
let cleaned = input.trimmingCharacters(in: .whitespacesAndNewlines)
.components(separatedBy: .controlCharacters)
.joined()
Escaping Special Characters
Sometimes, we cannot remove a character outright, but we can “escape” it so it won’t be interpreted as code. For example, before storing user input that could appear in HTML, we replace < with < and & with &. This prevents script injection in chat messages or comments.
We rely on built-in Foundation methods or write small helpers for this.
Timing Strategies for Validation
Timing matters. Validate too early, and users get annoyed. Validate too late, and bad data seeps in.
On-the-Fly Validation
As we type, validation can catch errors, think of a phone number field that blocks letters immediately. This is useful for strict formats.
On Field Exit Validation
Another method is validating when a user leaves a field. This gives freedom while typing, but still alerts to mistakes before submission.
On Form Submission Validation
We always check everything again before allowing the form to submit. This double-checks that nothing slipped through (especially important if users paste data).
Implementing Validation and Sanitization in SwiftUI and UIKit
Credits: Sean Allen
Building secure forms in SwiftUI and UIKit takes different approaches, but the principles are the same. [2]
SwiftUI Approaches
SwiftUI is reactive. We track input with @State variables, and use computed properties to check validity. These lightweight mechanisms align well with best habits for secure mobile coding in iOS where reactive flows can cut off unsafe input earlier in the UI layer.
Using State Bindings and Computed Properties
For example, our login screen might look like this:
struct LoginView: View {
@State private var username: String = “”
@State private var password: String = “”
var isFormValid: Bool {
!username.isEmpty && !password.isEmpty
}
var body: some View {
Form {
TextField(“Username”, text: $username)
SecureField(“Password”, text: $password)
Button(“Login”) {
// Handle login
}
.disabled(!isFormValid)
}
}
}
Enabling/Disabling Actions Based on Validation State
We often disable the “Login” or “Submit” button until all fields are valid. This gives users immediate feedback, and it prevents accidental submissions.
Example: Login Form Validation Pattern
Add a computed property for email validity:
var isEmailValid: Bool {
let pattern = “[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}”
return NSPredicate(format: “SELF MATCHES %@”, pattern).evaluate(with: email)
}
Show an error message only if the user has typed something and it’s invalid.
UIKit Approaches
UIKit is imperative. We use delegates, target-actions, and sometimes our own validator classes.
Validator Classes and Delegate Methods
For each UITextField, we might create a validator and check in the delegate method:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Only allow numbers in phone field
if textField == phoneTextField {
let allowed = CharacterSet.decimalDigits
return string.rangeOfCharacter(from: allowed.inverted) == nil
}
return true
}
Inline Field Validation as User Types
We display inline error messages or change the border color of a field when the input is invalid.
Example: Email Validation Using NSPredicate
func isValidEmail(_ email: String) -> Bool {
let emailRegEx = “[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}”
let emailPred = NSPredicate(format:”SELF MATCHES %@”, emailRegEx)
return emailPred.evaluate(with: email)
}
We use this in the submit action or as the user types.
User Interface Feedback Techniques
Feedback is what guides our users to success, not frustration.
Visual Indicators for Invalid Input
We highlight text fields in red when input is invalid. Sometimes, we add an icon or shake animation.
Contextual Error Messages
Short, specific messages work best. “Email is invalid.” “Username already taken.” Avoid vague warnings.
Dynamic Control States
Buttons stay disabled until the form is valid. Invalid fields may block form submission until corrected.
Security and Best Practices
Security always means assuming the user might try to break things, even if by accident.
Combining Client-Side and Server-Side Validation
Client-side validation helps users fix mistakes right away. But on the server, we must re-validate and sanitize everything. Never trust data just because it passed on the client.
Re-Validating Data on Server
Server-side checks are the last line of defense. A user can always bypass client-side checks by using custom scripts, so we run the same (or stricter) validation after data leaves the device, especially to guard against common iOS injection issues involving SQL or URL input.
Leveraging System APIs and Frameworks
We use Apple’s built-in validation and sanitization tools whenever possible. This avoids bugs and keeps up with system security fixes.
Avoiding Reinventing Validation Logic
We resist the urge to write custom regex for email or phone unless necessary. Standard libraries are tested and maintained.
Restricting Input via UI Controls
A trick we use often: don’t let users enter bad data at all. SwiftUI and UIKit offer controls for this.
- Pickers (for dates or options)
- Steppers (for number ranges)
- Segmented controls (for fixed choices)
Each of these limits invalid input from the start.
Balancing Validation Strictness and User Experience

It’s tempting to make rules too strict. But overly tight validation frustrates users. We find a balance:
- Allow reasonable typos if harmless
- Give clear, timely feedback
- Don’t block form submission for minor mistakes
For example, we allow spaces in a full name, but not numbers. We don’t force phone numbers to include hyphens, but we format them after submission.
FAQ
How do SwiftUI validation patterns differ from UIKit validation techniques in real projects?
In real-world iOS projects, SwiftUI validation usually relies on modifiers, onChange, and reactive state (@State, @Binding) to monitor and handle user input. UIKit validation uses delegate methods like UITextFieldDelegate to enforce input constraints and manage error feedback through labels or alerts.
While SwiftUI provides a more declarative approach, UIKit offers more granular control with UIKit validation class implementations and conditional form logic during form submission check.
What’s the best way to prevent invalid characters using regular expressions in Swift?
To limit input in text fields, you can use regular expressions Swift paired with Swift character set checks during UITextFieldDelegate calls or inside SwiftUI onChange closures.
For example, filtering for allowed characters Swift like [a-zA-Z0-9] helps with injection prevention and improves SwiftUI validation logic. Combine regex with Swift pattern matching to catch subtle issues like script injection or XSS protection.
How should Swift developers handle user input filtering before form submission?
Always combine client-side validation with server-side validation. On the device, use SwiftUI text field or UIKit text field with Swift string trimming, input length check, and text field sanitization. This improves SwiftUI form stability and avoids crashes.
Before submission, recheck all data using your SwiftUI validation handler or UIKit delegate validation. Ensure each Swift data cleaning rule strips or escapes special characters for SQL injection prevention or unsafe HTML.
What’s the right way to give users clear form validation feedback in SwiftUI?
Use SwiftUI validation feedback with real-time UI responses like SwiftUI error message under each input. Add SwiftUI disabled button logic that prevents submission if SwiftUI validation rules fail.
Pair this with SwiftUI conditional UI, like changing border colors or showing SwiftUI alerts. Make sure your SwiftUI validation function is readable and triggers using SwiftUI onChange. This helps users understand what went wrong without feeling frustrated.
How do you sanitize sensitive inputs like passwords or emails in iOS apps?
Start with SwiftUI password validation and SwiftUI email validation using SwiftUI regex or Swift computed properties. Use input constraints to limit length and structure. Apply Swift data cleaning techniques like trimming, lowercasing, or escaping user input.
Always check with SwiftUI validation pattern to prevent typos or invalid formats. In UIKit, set auto-correction Swift to false for password fields and use input masking where needed for clarity and iOS secure input.
Conclusion
The best input validation habits are the ones users never notice. Smooth forms, no weird errors, no silent data loss. But behind that simplicity is constant, careful work, validating, sanitizing, rechecking.
Whether you’re building in SwiftUI or UIKit, these practices matter. They stop the bugs you never see and block attacks before they happen. Want to get serious about writing secure iOS code? Make secure habits part of every project, every time. Join the Secure Coding Practices Bootcamp
References
- https://medium.com/@use.abhiram/input-validation-and-sanitization-protecting-your-application-from-malicious-input-28fee92ea0d3
- https://asynclearn.medium.com/using-uikit-in-swiftui-9f1527e576b8