如何在SwiftUI中使用Observable Object和NavigationLink绑定



我是Swift和SwiftUI的新手,正在练习属性包装器。我创建了一个简单的应用程序,你可以点击伦敦、纽约或迈阿密。一旦你点击其中一个,它将导航到自己的屏幕,显示城市名称、当前时间和新冠肺炎死亡人数。

我并没有把它和API连接起来,我只是想练习。我花了将近8个小时试图找到一种方法,让城市在第二个视图中显示自己的房产,而不必创建3个单独的视图模型。每个导航目的地都展示了伦敦的房产。我正在试图找到一种方法来修复它。我还从可识别模型创建了3个对象/实例。如果你能帮我的话,非常感谢。

这是我的视图模型:

class CityViewModel: ObservableObject {

@Published var title = "London"
@Published var deaths = "5894"
@Published var time = "8:36"
}

现在是我的内容视图:

struct ContentView: View {
@ObservedObject var cities = CityViewModel()


var body: some View {
NavigationView {
ZStack {
Color.black
.ignoresSafeArea()

VStack {

NavigationLink(
destination: ToogleView(cityname: self.$cities.title, deaths: self.$cities.deaths, time: self.$cities.time),
label: {
Text("London")
.foregroundColor(.white)
.bold()
.font(.system(size: 30))

})
Spacer()
NavigationLink(
destination: ToogleView(cityname: self.$cities.title, deaths: self.$cities.deaths, time: self.$cities.time),
label: {
Text("New York")
.foregroundColor(.white)
.bold()
.font(.system(size: 30))
})

我为单击Navigationlink时创建了第二个视图

struct ToogleView: View {
@Binding var cityname:String
@Binding var deaths:String
@Binding var time:String


var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Spacer()
Text(cityname)
.foregroundColor(.white)
.font(.system(size: 24))
.bold()
Spacer()
Text(time)
.foregroundColor(.white)
.font(.system(size: 18))
Spacer()
HStack{
Image(systemName: "person.3.fill")
.foregroundColor(.white)
Text(deaths)
.foregroundColor(.red)
.bold()




}
Spacer()
}
}
}
}

您将需要将数据存储在某些位置,因为您不想使用api并避免不同的视图模型,所以这里是一个选项。

创建一个名为City的swift文件,并添加以下内容:

struct City: Identifiable {
let id = UUID()
let name: String
let deaths: Int
let time: String
}

然后在CityViewModel中创建实例

let myChosenCities = [City(name: "London", deaths: 3252, time: "8:32"),
City(name: "Japan", deaths: 3461, time: "4:21"),
City(name: "Canada", deaths: 2352, time: "9:93")
]

然后修改您的视图,使其在像这样初始化时接受一个城市。

struct ToogleView: View {
let city: City
var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Spacer()
Text(city.name)
.foregroundColor(.white)
.font(.system(size: 24))
.bold()
Spacer()
Text(city.time)
.foregroundColor(.white)
.font(.system(size: 18))
Spacer()
HStack{
Image(systemName: "person.3.fill")
.foregroundColor(.white)
Text(String(city.deaths))
.foregroundColor(.red)
.bold()
}
Spacer()
}
}
}
}

然后将您的家长视图更改为:

struct ContentView: View {
@ObservedObject var vm = CityViewModel()

var body: some View {
NavigationView {
ZStack {
Color.black
.ignoresSafeArea()

VStack {
List(vm.myChosenCities) { city in
NavigationLink(destination: ToogleView(city: city)) {
HStack {
VStack {
Text(city.name)
Text(city.time)
}
Text(String(city.deaths))
}
}
}
}
}
}
}
}

以及您的视图模型:

class CityViewModel: ObservableObject {

let myChosenCities = [City(name: "London", deaths: 3252, time: "8:32"),
City(name: "Japan", deaths: 3461, time: "4:21"),
City(name: "Canada", deaths: 2352, time: "9:93")
]
}

我把你的例子做成了一个易于组织的列表,但你应该能够看到它是如何工作的

它到处显示伦敦的房产,因为您在ViewModel中对伦敦的房产进行了硬编码。

我建议创建一个城市模型,并将您想要显示的城市模型传递到ToggleView 中

下面的例子也是非常静态的,如果你想使用城市的动态数据,需要进行调整

class CityViewModel: ObservableObject {
@Published var city: [CityModel] = [
CityModel(title: "London", deaths: 5894, time: "8:36"),
CityModel(title: "New York", deaths: 2332, time: "3:36")
]
}
struct CityModel {
var title: String
var deaths: Int
var time: String
}

contentView

struct ContentView: View {
@ObservedObject var cities = CityViewModel()
var body: some View {
NavigationView {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
NavigationLink(
destination: ToogleView(city: cities.city.first!),
label: {
Text("London")
.foregroundColor(.white)
.bold()
.font(.system(size: 30))
})
Spacer()
NavigationLink(
destination: ToogleView(city: cities.city.last!),
label: {
Text("New York")
.foregroundColor(.white)
.bold()
.font(.system(size: 30))
})
}
}
}
}
}

切换查看

struct ToogleView: View {
var city: CityModel
var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Spacer()
Text(city.title)
.foregroundColor(.white)
.font(.system(size: 24))
.bold()
Spacer()
Text(city.time)
.foregroundColor(.white)
.font(.system(size: 18))
Spacer()
HStack{
Image(systemName: "person.3.fill")
.foregroundColor(.white)
Text(String(city.deaths))
.foregroundColor(.red)
.bold()
}
Spacer()
}
}
}
}

最新更新