I am writing my first project in Swift(I have been doing ObjectiveC for years) and for some reason, I cant work out why my enum and Switch are not working togetber
我在Swift编写我的第一个项目(我已经做了多年的ObjectiveC)并且由于某种原因,我无法解决为什么我的枚举和Switch没有工作的问题
enum ContactViewMode : Int
{
case ViewModeFavourite = 0
case ViewModeRecent = 1
case ViewModeContacts = 2
}
Property
属性
@IBInspectable var contactViewMode : Int!
Switch
开关
switch contactViewMode {
case ContactViewMode.ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode.ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
The error I get is Enum case 'ViewModeFavourite' is not a member of type 'Int!'
我得到的错误是Enum case'ViewModeFavourite'不是'Int!'类型的成员
So I changed it to this as it is not a Int! (I need Int! for Storyboard)
所以我改为它,因为它不是Int! (我需要Int!for Storyboard)
var contactMode:Int = contactViewMode
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
Then I get Enum case pattern cannot match values of the non-enum type 'Int'
然后我得到Enum案例模式不能匹配非枚举类型'Int'的值
6 个解决方案
#1
26
You have to declare contactViewMode
as ContactViewMode
and not Int
.
您必须将contactViewMode声明为ContactViewMode而不是Int。
If you really want it to be Int
, then you have to change the cases in your switch, by comparing the variable to the rawValue
property of the enum cases:
如果你真的希望它是Int,那么你必须通过比较变量和枚举情况的rawValue属性来改变你的开关中的情况:
switch contactViewMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode.ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
but unless you have a good reason for that, I wouldn't recommend
但除非你有充分理由,否则我不建议
#2
18
The other answers fail to take advantage of Swift’s strong typing. Note that they all have a default
case in their switch
. Swift can know at compile time, however, whether you have covered all cases of an enum
or not, thus rendering the default
case unnecessary.
其他答案未能利用Swift的强力打字。请注意,它们的开关中都有默认大小写。但是,Swift可以在编译时知道你是否已经覆盖枚举的所有情况,因此不需要渲染默认情况。
This is a useful feature of the language. Imagine you add an extra case
to your enum
at a later point. The compiler will complain and point you to all the switch
es that are not considering that particular case
.
这是该语言的一个有用功能。想象一下,您稍后会在枚举中添加一个额外的案例。编译器会抱怨并指向所有不考虑该特定情况的交换机。
How can we take advantage of Swift’s strong typing, then?
那么我们怎样才能利用Swift强大的打字?
First, let’s fix the naming of your enumeration. As I assume you are putting this inside a ContactView
class (and, unlike in Objective-C, it should really be inside it), you can name the enum
simply Mode
. No need to mention ViewMode
s in the cases either. This way you get a cleaner, more idiomatic type.
首先,让我们修复枚举的命名。我假设你把它放在一个ContactView类中(并且,与Objective-C不同,它应该真的在它里面),你可以简单地命名枚举。在这些情况下也无需提及ViewModes。通过这种方式,您可以获得更清洁,更惯用的类型。
enum Mode: Int {
case Favourite
case Recent
case Contacts
}
What we need to do is to perform the switch
on a Mode
, not on an Int
. Your Mode
is RawRepresentable
, and as such you can do:
我们需要做的是在模式上执行切换,而不是在Int上执行。您的模式是RawRepresentable,因此您可以这样做:
guard let m = Mode(rawValue: contactViewMode) else { /* handle the situation */ }
switch m {
case .Favourite: /* handle case */
case .Recent: /* handle case */
case .Contacts: /* handle case */
}
That’s all there is to—instead of switching on the rawValue
, get the proper Mode
first and then switch on it.
这就是 - 而不是打开rawValue,首先获得正确的模式,然后打开它。
#3
6
This worked for me:
这对我有用:
I have an enum like this:
我有这样的枚举:
enum Proximity{
case Unknown
case Immediate
case Near
case Far
}
Then a switch that looks like this:
然后是一个如下所示的开关:
switch b.proximity as Proximity {
case Proximity.Immediate:
if b.rssi == -30 && b.accuracy == 0.2345{
closestBeacon = b
}
case Proximity.Near:
return
case Proximity.Far:
return
default:
return
}
Im looping through an array of "b" objects that have a proximity property.
我循环遍历具有邻近属性的“b”对象数组。
#4
4
Enumerations are types. Just because you make clear that the single enum values can be cast to Int
doesn't make it valid to declare contactViewMode
an Int!
. The types simply don't match.
枚举是类型。只是因为你明确表示单个枚举值可以强制转换为Int并不能使contactViewMode声明为Int!。类型根本不匹配。
So either declare contactViewMode
as ContactViewMode
, use your first switch
statement and cast to Int!
when you actually need it for the storyboard, or use the second switch
, but don't use .ViewModeFacourite
et al, but the corresponding Int
value.
因此要么将contactViewMode声明为ContactViewMode,请使用您的第一个switch语句并转换为Int!当你真的需要它为故事板,或使用第二个开关,但不要使用.ViewModeFacourite等,但相应的Int值。
var contactMode:Int = contactViewMode
switch contactMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode..ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
#5
3
You cannot directly match Int
with enum
. Instead, you have to convert ContactViewMode
to Int
with .rawValue
property, OR convert Int
to ContactViewMode
with init(rawValue:)
initializer.
你不能直接匹配Int与枚举。相反,您必须使用.rawValue属性将ContactViewMode转换为Int,或者使用init(rawValue :)初始化程序将Int转换为ContactViewMode。
The latter example:
后一个例子:
switch ContactViewMode(rawValue: contactViewMode) {
case .Some(.ViewModeFavourite):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .Some(.ViewModeRecent):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
because ContactViewMode(rawValue:)
returns Optionals, we need .Some()
.
因为ContactViewMode(rawValue :)返回Optionals,我们需要.Some()。
#6
1
You can simply use contactViewMode and create a new var of type ContactViewMode
in case value of contactViewMode
is coming from somewhere else and it has to be int
.
你可以简单地使用contactViewMode并创建一个类型为ContactViewMode的新var,以防contactViewMode的值来自其他地方而且必须是int。
let contactMode :ContactViewMode = ContactViewMode(rawValue: contactViewMode)!
Now you can easily use switch as shown below:
现在您可以轻松使用switch,如下所示:
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
#1
26
You have to declare contactViewMode
as ContactViewMode
and not Int
.
您必须将contactViewMode声明为ContactViewMode而不是Int。
If you really want it to be Int
, then you have to change the cases in your switch, by comparing the variable to the rawValue
property of the enum cases:
如果你真的希望它是Int,那么你必须通过比较变量和枚举情况的rawValue属性来改变你的开关中的情况:
switch contactViewMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode.ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
but unless you have a good reason for that, I wouldn't recommend
但除非你有充分理由,否则我不建议
#2
18
The other answers fail to take advantage of Swift’s strong typing. Note that they all have a default
case in their switch
. Swift can know at compile time, however, whether you have covered all cases of an enum
or not, thus rendering the default
case unnecessary.
其他答案未能利用Swift的强力打字。请注意,它们的开关中都有默认大小写。但是,Swift可以在编译时知道你是否已经覆盖枚举的所有情况,因此不需要渲染默认情况。
This is a useful feature of the language. Imagine you add an extra case
to your enum
at a later point. The compiler will complain and point you to all the switch
es that are not considering that particular case
.
这是该语言的一个有用功能。想象一下,您稍后会在枚举中添加一个额外的案例。编译器会抱怨并指向所有不考虑该特定情况的交换机。
How can we take advantage of Swift’s strong typing, then?
那么我们怎样才能利用Swift强大的打字?
First, let’s fix the naming of your enumeration. As I assume you are putting this inside a ContactView
class (and, unlike in Objective-C, it should really be inside it), you can name the enum
simply Mode
. No need to mention ViewMode
s in the cases either. This way you get a cleaner, more idiomatic type.
首先,让我们修复枚举的命名。我假设你把它放在一个ContactView类中(并且,与Objective-C不同,它应该真的在它里面),你可以简单地命名枚举。在这些情况下也无需提及ViewModes。通过这种方式,您可以获得更清洁,更惯用的类型。
enum Mode: Int {
case Favourite
case Recent
case Contacts
}
What we need to do is to perform the switch
on a Mode
, not on an Int
. Your Mode
is RawRepresentable
, and as such you can do:
我们需要做的是在模式上执行切换,而不是在Int上执行。您的模式是RawRepresentable,因此您可以这样做:
guard let m = Mode(rawValue: contactViewMode) else { /* handle the situation */ }
switch m {
case .Favourite: /* handle case */
case .Recent: /* handle case */
case .Contacts: /* handle case */
}
That’s all there is to—instead of switching on the rawValue
, get the proper Mode
first and then switch on it.
这就是 - 而不是打开rawValue,首先获得正确的模式,然后打开它。
#3
6
This worked for me:
这对我有用:
I have an enum like this:
我有这样的枚举:
enum Proximity{
case Unknown
case Immediate
case Near
case Far
}
Then a switch that looks like this:
然后是一个如下所示的开关:
switch b.proximity as Proximity {
case Proximity.Immediate:
if b.rssi == -30 && b.accuracy == 0.2345{
closestBeacon = b
}
case Proximity.Near:
return
case Proximity.Far:
return
default:
return
}
Im looping through an array of "b" objects that have a proximity property.
我循环遍历具有邻近属性的“b”对象数组。
#4
4
Enumerations are types. Just because you make clear that the single enum values can be cast to Int
doesn't make it valid to declare contactViewMode
an Int!
. The types simply don't match.
枚举是类型。只是因为你明确表示单个枚举值可以强制转换为Int并不能使contactViewMode声明为Int!。类型根本不匹配。
So either declare contactViewMode
as ContactViewMode
, use your first switch
statement and cast to Int!
when you actually need it for the storyboard, or use the second switch
, but don't use .ViewModeFacourite
et al, but the corresponding Int
value.
因此要么将contactViewMode声明为ContactViewMode,请使用您的第一个switch语句并转换为Int!当你真的需要它为故事板,或使用第二个开关,但不要使用.ViewModeFacourite等,但相应的Int值。
var contactMode:Int = contactViewMode
switch contactMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode..ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
#5
3
You cannot directly match Int
with enum
. Instead, you have to convert ContactViewMode
to Int
with .rawValue
property, OR convert Int
to ContactViewMode
with init(rawValue:)
initializer.
你不能直接匹配Int与枚举。相反,您必须使用.rawValue属性将ContactViewMode转换为Int,或者使用init(rawValue :)初始化程序将Int转换为ContactViewMode。
The latter example:
后一个例子:
switch ContactViewMode(rawValue: contactViewMode) {
case .Some(.ViewModeFavourite):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .Some(.ViewModeRecent):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
because ContactViewMode(rawValue:)
returns Optionals, we need .Some()
.
因为ContactViewMode(rawValue :)返回Optionals,我们需要.Some()。
#6
1
You can simply use contactViewMode and create a new var of type ContactViewMode
in case value of contactViewMode
is coming from somewhere else and it has to be int
.
你可以简单地使用contactViewMode并创建一个类型为ContactViewMode的新var,以防contactViewMode的值来自其他地方而且必须是int。
let contactMode :ContactViewMode = ContactViewMode(rawValue: contactViewMode)!
Now you can easily use switch as shown below:
现在您可以轻松使用switch,如下所示:
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}