Switch:Enum Switch问题:不是int的成员

时间:2022-07-09 16:23:41

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 switches 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 ViewModes 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 switches 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 ViewModes 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]
        }