swiftUI笔记之async&await实践MVVM网络请求

实践

我们来实践一下使用MVVM模式,并使用async await进行网络请求。

XfOeyo

Library.swift

1
2
3
4
5
import Foundation
struct Common: Codable,Hashable {
var act: String = ""
var prompt: String = ""
}

LibraryViewModel.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Foundation
@MainActor
class LibraryViewModel: ObservableObject {
@Published var commons: [Common] = []
@Published var commonSelected:Common = Common()
func getCommons() async {
guard let url = URL(string: "https://carteclip.com/api/v1/ama/prompts") else {
print("URL无效,请检查输入~")
return
}
do {
var request = URLRequest(url: url)
request.setValue("zh", forHTTPHeaderField: "prefer-language")
let (data, _) = try await URLSession.shared.data(
for: request
)
if let decodedResponse = try? JSONDecoder().decode([Common].self, from: data) {
self.commons = decodedResponse
}
} catch {
print("数据解码失败,请检查~")
}
}
}

LibraryView.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import SwiftUI
struct LibraryRow: View {
var common: Common
var body: some View {
VStack(alignment: .leading) {
Spacer()
Text(common.act)
.listRowSeparator(.hidden)
.font(.system(size: 18))
.frame(maxWidth: .infinity, alignment: .leading)

Spacer()
Text(common.prompt)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.system(size: 15))
.lineLimit(3)
Spacer()
}
}

}
struct LibraryView: View {
@State var presentSheetKey = false
@State var cur_common:Common = Common(act: "", prompt: "")
@ObservedObject var viewModel: LibraryViewModel
var body: some View {
NavigationStack {
List(viewModel.commons,id: \.self) { common in
Section{
Button {
viewModel.commonSelected = common
presentSheetKey = true
} label: {
LibraryRow(common:common).listRowSeparator(.hidden)
}.buttonStyle(.plain)

}
}.task {
await viewModel.getCommons()
}.refreshable {
await viewModel.getCommons()
}
}.sheet(isPresented: $presentSheetKey) {
VStack(alignment: .leading,spacing: 20) {
Text(viewModel.commonSelected.act).font(.system(size: 17)).foregroundColor(.primary)
Text(viewModel.commonSelected.prompt).font(.system(size: 15)).foregroundColor(.secondary).lineSpacing(8)
Spacer()
HStack(alignment: .bottom,spacing: 20){
Spacer()
Button {
presentSheetKey = false
} label: {
Text("取消").foregroundColor(.primary)
}
Button {

} label: {
Text("开始对话").foregroundColor(.primary)
}
}


}.padding()
.presentationDetents([.fraction(0.5),.medium])
.presentationBackground(.thinMaterial)
.presentationCornerRadius(20)
.presentationDragIndicator(.visible)
}

}
}
struct LibraryView_Previews: PreviewProvider {
static var previews: some View {
LibraryView( viewModel: LibraryViewModel())
}
}

LibraryDetailView.swift

1
2
3
4
5
6
7
8
9
10
11

import Foundation
import SwiftUI

struct LibraryDetailView: View {
var common:Common
@Environment(\.dismiss) var dismiss
var body: some View {
Text(common.prompt)
}
}