Implementing Edit Functionality and Component Reuse in a SwiftUI LinkWorld App
This article walks through the design and implementation of an edit screen for the LinkWorld iOS app, showing how to refactor shared UI parts into reusable SwiftUI components, bind them to a data model, and handle navigation, modal presentation, and update logic using a view‑model.
In the seventh chapter of the LinkWorld tutorial we add the missing edit capability for identity cards, completing the CRUD cycle (Create, Read, Update, Delete) for the app.
Component analysis : Because the add‑new and edit screens share many UI elements (title input, platform picker, URL editor), we extract these into three reusable SwiftUI views – TitleInputView , PlatformPicker , and IndexURLView . Each view receives its data via @Binding properties, allowing two‑way synchronization with the parent view.
Creating the reusable components :
import SwiftUI
struct TitleInputView: View {
@Binding var title: String
var body: some View {
TextField("请输入头衔", text: $title)
.padding()
.background(Color(.systemGray6))
.cornerRadius(8)
.padding(.horizontal)
.disableAutocorrection(true)
.autocapitalization(.none)
}
}
struct PlatformPicker: View {
@Binding var platformIcon: String
@Binding var platformName: String
let platforms = [
("稀土掘金技术社区", "icon_juejin"),
("CSDN博客", "icon_csdn"),
("阿里云社区", "icon_aliyun"),
("华为云社区", "icon_huaweiyun")
]
var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
var body: some View {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 10) {
ForEach(0..After creating these components we replace the duplicated code in NewView with calls to the new views, dramatically reducing the source size while keeping the UI unchanged.
Designing the Edit screen : A new SwiftUI file EditView.swift is added. It uses a NavigationStack with a title, a close button, and the three reusable components bound to a Model instance. An "Update" button calls the view‑model to persist changes.
import SwiftUI
struct EditView: View {
@Environment(.presentationMode) var presentationMode
@State var model: Model
var viewModel: ViewModel
var body: some View {
NavigationStack {
VStack(spacing: 15) {
TitleInputView(title: $model.title)
PlatformPicker(platformIcon: $model.platformIcon, platformName: $model.platformName)
IndexURLView(indexURL: $model.indexURL)
updateBtn()
Spacer()
}
}
.navigationBarTitle("编辑身份卡", displayMode: .inline)
.navigationBarItems(trailing: closeBtn())
}
// close button
func closeBtn() -> some View { /* … */ }
// update button
func updateBtn() -> some View { /* … */ }
}The edit flow is wired in ContentView : tapping the ellipsis icon toggles showEditView , which presents EditView as a sheet. The model of the selected card is passed to the edit view, and the view‑model’s editItem(item:) method updates the underlying array.
// editItem implementation in ViewModel
func editItem(item: Model) {
if let id = models.firstIndex(where: { $0.id == item.id }) {
models[id] = item
}
}To avoid navigation conflicts, the original NavigationLink to the home page is commented out and replaced with a fullScreenCover triggered by tapping the main card container. The cover presents HomePageView and hides the safe area for a seamless full‑screen experience.
.fullScreenCover(isPresented: $showHomePageView) {
HomePageView(platformName: platformName, indexURL: indexURL)
.edgesIgnoringSafeArea(.all)
}Finally, the chapter concludes with a project summary, emphasizing the benefits of component‑based architecture and previewing the next steps—adding local and remote data storage.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.