Implementing MVVM Architecture and Network Requests in a SwiftUI Mobile App
This tutorial walks through building a minimal MVP for the Linkworld iOS app by applying the MVVM pattern, creating a ViewModel, fetching JSON data with URLSession, and adding, editing, and deleting identity cards using SwiftUI state management and context menus.
In earlier chapters the basic functionality of the Linkworld app was completed, but it lacked local storage, network requests, and CRUD operations, preventing it from being a minimal viable product (MVP). This section continues the development to achieve a full MVP.
The MVVM (Model-View-ViewModel) architecture is introduced for SwiftUI projects: the Model abstracts data, the View defines the UI, and the ViewModel binds them together. In the project, Model files represent the data layer, ContentView, NewView, and HomePageView are the Views, and a new Swift file named ViewModel.swift is created to hold the ViewModel.
The ViewModel is defined as an ObservableObject with a published array of Model instances:
import Foundation
import SwiftUI
class ViewModel: ObservableObject {
@Published var models = [Model]()
}To fetch remote data, a JSON file is prepared on a third‑party service (e.g., npoint.io). The JSON structure contains an array of objects matching the Model fields. The URL is stored in a constant:
let JsonURL = "https://api.npoint.io/c51968c99a2a087dac5e"A network request method getData() is added to the ViewModel using URLSession . The response is decoded with JSONDecoder into [Model] and assigned to models :
//网络请求
func getData() {
let session = URLSession(configuration: .default)
session.dataTask(with: URL(string: JsonURL)!) { data, _, _ in
guard let jsonData = data else { return }
do {
let data = try JSONDecoder().decode([Model].self, from: jsonData)
self.models = data
} catch {
print(error)
}
}
.resume()
}The ViewModel is instantiated in the UI with @StateObject var viewModel = ViewModel() , allowing all views to access the shared data. The original @State array in ContentView is replaced by viewModel.models , and the list now displays the fetched JSON items.
CRUD methods are moved into the ViewModel. An addCard(newItem: Model) method appends a new model to the array, and a deleteItem(itemId: UUID) method removes an item by its identifier:
// 创建身份卡
func addCard(newItem: Model) {
models.append(newItem)
}
// 删除身份卡片
func deleteItem(itemId: UUID) {
models.removeAll { $0.id == itemId }
}In NewView , the ViewModel is injected so that new cards are added via viewModel.addCard(newItem: newItem) . The view is previewed with NewView(viewModel: ViewModel()) . In ContentView , a context menu is attached to each card to trigger deletion:
// 卡片视图
CardView(platformIcon: item.platformIcon, title: item.title, platformName: item.platformName, indexURL: item.indexURL)
// 长按唤起删除
.contextMenu {
Button(action: {
self.viewModel.deleteItem(itemId: item.id)
}) {
Text("删除")
}
}The chapter concludes that the Linkworld project now supports MVVM‑structured code, network‑driven JSON loading, and basic add/delete operations, laying the groundwork for further features such as editing, sorting, and alternative deletion interactions in upcoming sections.
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.