我的内容 View 是:
struct ContentView {
@State private var calendar = Bundle.main.decode(Calendar.self, from: "calendar.json")
var body: some View {
NavigationView {
.... Content that loops through calendar and displays events in a list
}
.onAppear {
self.getData()
}
}
}
func getData() {
let url = "<URL goes here>"
let encoded = "<JSON FOR REQUEST>"
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let encoder = JSONEncoder()
if let data = try? encoder.encode(encoded) {
request.httpBody = data
}
URLSession.shared.dataTask(with: request) { data1, response, error in
// DECODE the response and process the data
if let data1 = data1 {
let decoder = JSONDecoder()
if let calendar = try? decoder.decode(IDCCalendar.self, from: data1)
{
self.calendar = calendar
}
else {
print("Does not decode correctly")
}
}
else {
print("error with data1")
}
}.resume()
}
这是我的问题:日历变量需要初始化,因此我使用名为 calendar.json 的文件中的虚拟数据来初始化它。理想情况下,我只想声明 @State private var calendar : 日历 并让网络请求填充变量。使用虚拟数据方法,当应用程序加载时,首先出现虚拟数据,然后在网络调用完成时被实际数据替换。
任何解决此问题的建议将不胜感激。
最佳答案
如果您使用可选值,则无需为其设置初始值。您的View
可以根据变量是否nil
或有值进行有条件地渲染。
一般来说,异步请求不应在 View
内完成,因此我已将逻辑移至 ObservableObject
:
class ViewModel : ObservableObject {
@Published var calendar : CalendarModel?
func getData() {
//get data from API and set self.calendar with result
}
}
struct ContentView {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationView {
Group {
if let calendar = viewModel.calendar {
//use `calendar` variable here
} else {
Text("Loading...")
}
}
}
.onAppear {
viewModel.getData()
}
}
}
您还可以通过执行以下操作将日历 View 重构为其自己的组件(具有非可选属性):
struct ContentView {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationView {
Group {
if let calendar = viewModel.calendar {
CalendarView(calendar: calendar)
} else {
Text("Loading...")
}
}
}
.onAppear {
viewModel.getData()
}
}
}
struct CalendarView : View {
var calendar : CalendarModel
var body: some View {
//render calendar
}
}
(注意:我使用了 CalendarModel,因为您没有包含类型的代码,并且您同时使用了 Calendar
和 IDCCalendar
,而且我不确定区别是什么。另外,请注意与 Calendar
的命名空间冲突,因为 Foundation 中已经有一个名为该类型的类型)
关于swiftui - 当变量被网络请求填充时如何初始化变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67373165/