如何在 SwiftUI 中使用可观察对象并与 NavigationLink 绑定?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中使用可观察对象并与 NavigationLink 绑定?【英文标题】:How do I use Observable Object and Binding with the NavigationLink in SwiftUI? 【发布时间】:2021-03-21 09:18:41 【问题描述】:我是 Swift 和 SwiftUI 的新手,我正在练习使用属性包装器。我创建了一个简单的应用程序,您可以在其中单击伦敦、纽约或迈阿密。一旦您点击其中任何一个,它将导航到它自己的屏幕,该屏幕将显示城市名称、当前时间和 covid 死亡人数。
我没有将它连接到我只是想练习的 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()
【问题讨论】:
【参考方案1】:好吧,您将需要在某个地方存储数据,因为您不想使用 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))
你的 viewModel 是这样的:
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")
]
我将您的示例列在一个列表中以便于组织,但您应该能够看到它是如何工作的
【讨论】:
非常感谢!!! :) 我现在也有了更好的理解。@ObservedObject
仅应在对象的所有者不是视图本身时使用。在此示例中,您应该使用 @StateObject
代替,当视图是 ObservableObject
对象的实际所有者时应该使用它【参考方案2】:
因为您在 ViewModel 中硬编码了伦敦的属性,所以它到处都显示了伦敦的属性。
我建议创建一个城市模型并将您想要显示的 CityModel 传递到 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
内容视图
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()
【讨论】:
感谢沃尔克 :)以上是关于如何在 SwiftUI 中使用可观察对象并与 NavigationLink 绑定?的主要内容,如果未能解决你的问题,请参考以下文章
如何将可观察对象发布的整数变量绑定到 SwiftUI 中的 textField?
SwiftUI-> 线程 1:致命错误:未找到 MyObject.Type 类型的可观察对象(工作表中的 EnvironmentObject)
SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject