Rewrite a UIKit name-form view controller as SwiftUI
The UIKit controller below shows a name text field, a Save button, and a success message that is hidden until the user saves a non-empty name. Rewrite it as an idiomatic SwiftUI view.
Requirements:
- Use
@Statefor the name and the greeting; no manualisHiddentoggling. - Two-way bind the text field; the greeting appears only when the name is non-empty.
- Use declarative layout (
VStack/padding), notNSLayoutConstraint.
struct NameFormView: View {
var body: some View {
// your code here
}
}
Write the implementation.
Replace the controller with a View holding @State for name and greeting. TextField("Name", text: $name) binds the input, a Button sets the greeting, and if !greeting.isEmpty { Text(greeting) } replaces isHidden. A VStack with padding replaces Auto Layout.
- ✗Reaching for
UIViewControllerRepresentableinstead of writing a native SwiftUI view - ✗Toggling visibility with a flag instead of conditional view inclusion (
if ...) - ✗Keeping manual Auto Layout constraints rather than stack-based declarative layout
- →Why does
if !greeting.isEmptyremove a view rather than just hide it? - →How does
$namekeep theTextFieldand the model in sync without target-action?
A native SwiftUI view replaces ~40 lines of UIKit boilerplate:
struct NameFormView: View {
@State private var name = ""
@State private var greeting = ""
var body: some View {
VStack(alignment: .leading, spacing: 20) {
Text("Enter your name:")
TextField("Name", text: $name)
.textFieldStyle(.roundedBorder)
Button("Save") {
greeting = name.isEmpty ? "" : "Hello, \(name)!"
}
if !greeting.isEmpty {
Text(greeting).foregroundColor(.green)
}
Spacer()
}
.padding()
}
}
$name two-way binds the field to state — no target-action, no manual reads. if !greeting.isEmpty conditionally includes the Text (it leaves the hierarchy entirely, not just becomes hidden), replacing the isHidden flag. The VStack/padding chain replaces all the Auto Layout constraints and the translatesAutoresizingMaskIntoConstraints boilerplate.