访问 ObservableObject 中的枚举
Accessing an enum in ObservableObject
我正在尝试重构我拥有的一些代码,并认为我能够将一些代码从可全局访问的枚举移动到应用程序的 ViewModel 中。
但是,当我尝试从视图访问它时,它似乎无法访问,甚至在自动完成中也没有选项。
我想知道出现这种情况是否有原因,我是否遗漏了什么..
// view
struct MyView: View {
@StateObject var vm = MyViewModel()
var body: some View {
ForEach(vm.MyEnum.allCases, id: \.self) { item in
...
}
}
}
// view model
final class MyViewModel: ObservableObject {
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
我似乎能够访问视图模型中的所有其他内容,但在涉及枚举时却不能。我尝试阅读枚举以了解原因,但我遇到的大多数事情主要是“操作方法”,而没有深入探讨原因。
你的问题不是关于 enum
s,它更多的是关于属性与类型。当您这样做时:
final class MyViewModel: ObservableObject {
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
...您正在定义 2 种类型。
MyViewModel
,这是一个class
MyEnum
,这是一个 enum
您的 MyEnum
嵌套在 MyViewModel
中并不重要 — 它仍然只是一种类型,而不是 属性。
属性使用 let
或 var
声明。例如:
final class MyViewModel: ObservableObject {
let myEnumArray = [MyEnum.a, MyEnum.b, MyEnum.c] /// create an instance property
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
struct MyView: View {
@StateObject var vm = MyViewModel()
var body: some View {
/// access the instance property here!
ForEach(vm.myEnumArray, id: \.self) { item in
/// ...
}
}
}
在上面的代码中,我创建了一个新的 属性、myEnumArray
,您可以使用 vm.myEnumArray
访问它。这会起作用。
现在如果您想访问 MyEnum
的 allCases
怎么办?请注意,此 属性 是 static — 属性 属于类型本身,而不是类型的实例。这就是为什么它没有出现在您的自动完成中的原因。示例:
MyViewModel.MyEnum.allCases /// Works! The type is `MyViewModel.MyEnum` and I'm accessing the static `allCases` property.
@StateObject var vm = MyViewModel()
vm.MyEnum.allCases /// NO! the `MyEnum` property doesn't exist inside `vm`.
所以你的代码确实有 2 个问题。
- 你认为
MyEnum
是一个属性。不,是一种类型!
- 因为
MyEnum
是一种类型,所以您不能使用 vm.MyEnum
访问它(这就是您访问实例 属性 的方式)。你需要做 MyViewModel.MyEnum
.
固定代码如下:
struct MyView: View {
var body: some View {
ForEach(MyViewModel.MyEnum.allCases, id: \.self) { item in
/// ...
}
}
}
我正在尝试重构我拥有的一些代码,并认为我能够将一些代码从可全局访问的枚举移动到应用程序的 ViewModel 中。
但是,当我尝试从视图访问它时,它似乎无法访问,甚至在自动完成中也没有选项。
我想知道出现这种情况是否有原因,我是否遗漏了什么..
// view
struct MyView: View {
@StateObject var vm = MyViewModel()
var body: some View {
ForEach(vm.MyEnum.allCases, id: \.self) { item in
...
}
}
}
// view model
final class MyViewModel: ObservableObject {
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
我似乎能够访问视图模型中的所有其他内容,但在涉及枚举时却不能。我尝试阅读枚举以了解原因,但我遇到的大多数事情主要是“操作方法”,而没有深入探讨原因。
你的问题不是关于 enum
s,它更多的是关于属性与类型。当您这样做时:
final class MyViewModel: ObservableObject {
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
...您正在定义 2 种类型。
MyViewModel
,这是一个class
MyEnum
,这是一个enum
您的 MyEnum
嵌套在 MyViewModel
中并不重要 — 它仍然只是一种类型,而不是 属性。
属性使用 let
或 var
声明。例如:
final class MyViewModel: ObservableObject {
let myEnumArray = [MyEnum.a, MyEnum.b, MyEnum.c] /// create an instance property
enum MyEnum: String, CaseIterable {
case a, b, c
}
}
struct MyView: View {
@StateObject var vm = MyViewModel()
var body: some View {
/// access the instance property here!
ForEach(vm.myEnumArray, id: \.self) { item in
/// ...
}
}
}
在上面的代码中,我创建了一个新的 属性、myEnumArray
,您可以使用 vm.myEnumArray
访问它。这会起作用。
现在如果您想访问 MyEnum
的 allCases
怎么办?请注意,此 属性 是 static — 属性 属于类型本身,而不是类型的实例。这就是为什么它没有出现在您的自动完成中的原因。示例:
MyViewModel.MyEnum.allCases /// Works! The type is `MyViewModel.MyEnum` and I'm accessing the static `allCases` property.
@StateObject var vm = MyViewModel()
vm.MyEnum.allCases /// NO! the `MyEnum` property doesn't exist inside `vm`.
所以你的代码确实有 2 个问题。
- 你认为
MyEnum
是一个属性。不,是一种类型! - 因为
MyEnum
是一种类型,所以您不能使用vm.MyEnum
访问它(这就是您访问实例 属性 的方式)。你需要做MyViewModel.MyEnum
.
固定代码如下:
struct MyView: View {
var body: some View {
ForEach(MyViewModel.MyEnum.allCases, id: \.self) { item in
/// ...
}
}
}