Reputation: 5193
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
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!'
So I changed it to this as it is not a Int! (I need 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'
Upvotes: 27
Views: 22045
Reputation: 501
The other answers fail to take advantage of Swift’s strong typing. Note that they all have a default
case in their switch
. Swift knows at compile time, however, whether you have covered all cases of an enum
or not, thus rendering the default
case unnecessary.
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?
First, let’s fix the naming of your enumeration. As I assume you are nesting it 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.
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:
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 it—instead of switching on the rawValue
, get the proper Mode
first and then switch on it.
Upvotes: 27
Reputation: 79
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
.
let contactMode :ContactViewMode = ContactViewMode(rawValue: contactViewMode)!
Now you can easily use switch as shown below:
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
Upvotes: 1
Reputation: 5634
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.
Upvotes: 6
Reputation: 51911
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.
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()
.
Upvotes: 3
Reputation: 72760
You have to declare contactViewMode
as ContactViewMode
and not 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:
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
Upvotes: 34
Reputation: 56707
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.
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.
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]
}
Upvotes: 4