Skip to content

在ViewModel中使用async/await获取数据

在SwiftUI中,使用async/await可以极大地简化异步数据获取的过程。通过将异步操作与ViewModel结合,你可以更清晰地管理数据流和UI更新。

1. 创建ViewModel

首先,你需要创建一个ViewModel类,遵循ObservableObject协议。这使得你的ViewModel能够被SwiftUI视图观察。

swift
import SwiftUI
import Combine

class DataViewModel: ObservableObject {
    @Published var data: [String] = []
    @Published var errorMessage: String?
    
    func fetchData() async {
        do {
            let fetchedData = try await fetchFromNetwork()
            DispatchQueue.main.async {
                self.data = fetchedData
            }
        } catch {
            DispatchQueue.main.async {
                self.errorMessage = "数据获取失败: \(error.localizedDescription)"
            }
        }
    }
    
    private func fetchFromNetwork() async throws -> [String] {
        // 模拟网络请求
        let url = URL(string: "https://api.example.com/data")!
        let (data, _) = try await URLSession.shared.data(from: url)
        let decodedData = try JSONDecoder().decode([String].self, from: data)
        return decodedData
    }
}

2. 在视图中使用ViewModel

在SwiftUI视图中,你可以使用@StateObject来实例化ViewModel,并在视图中调用fetchData方法。

swift
struct ContentView: View {
    @StateObject private var viewModel = DataViewModel()
    
    var body: some View {
        VStack {
            if let errorMessage = viewModel.errorMessage {
                Text(errorMessage)
                    .foregroundColor(.red)
            } else {
                List(viewModel.data, id: \.self) { item in
                    Text(item)
                }
            }
        }
        .task {
            await viewModel.fetchData()
        }
    }
}

3. 处理UI更新

在上面的代码中,fetchData方法会在获取数据后更新data属性。由于data@Published,SwiftUI会自动重新渲染视图。

  • 错误处理:如果在获取数据时发生错误,errorMessage会被更新,SwiftUI会显示错误信息。
  • 异步任务:使用.task修饰符可以在视图加载时自动调用异步方法。

4. 优化数据获取

为了提高性能,可以考虑使用TaskTaskGroup来并行处理多个网络请求。这样可以减少等待时间,提高用户体验。

swift
func fetchMultipleData() async {
    await withTaskGroup(of: [String].self) { group in
        for i in 1...5 {
            group.addTask {
                return try await fetchFromNetwork(for: i)
            }
        }
        
        for await result in group {
            self.data.append(contentsOf: result)
        }
    }
}

通过这种方式,你可以在ViewModel中高效地管理异步数据获取,确保UI始终保持响应。使用async/await不仅使代码更简洁,还提高了可读性和可维护性。🎉

本站使用 VitePress 制作