NicolasMiari NicolasMiari - 4 months ago 7
Swift Question

Compiler error when comparing values of enum type with associated values?

class MyClass
{
enum MyEnum {
case FirstCase
case SecondCase(Int)
case ThirdCase
}

var state:MyEnum!

func myMethod ()
{
if state! == MyEnum.FirstCase {
// Do something
}
}
}


I get the compiler error pointing at the
if
statement::


Binary operator '==' cannot be applied to two 'MyClass.MyEnum'
operands


If instead, I use a
switch
statement, there is no problem:

switch state! {
// Also, why do I need `!` if state is already an
// implicitly unwrapped optional? Is it because optionals also
// are internally enums, and the compiler gets confused?

case .FirstCase:
// do something...

default:
// (do nothing)
break
}


However, the
switch
statement feels too verbose: I just want to
do something
for
.FirstCase
, and nothing otherwise. An
if
statement makes more sense.

What's going on with enums and
==
?

EDIT: This is ultra-weird. After settling for the
switch
version and moving on to other (totally unrelated) parts of my code, and coming back, the
if
-statement version (comnparing force-unwrapped property against fixed enum case) is compiling with no errors.
I can only conclude that it has something to do with some corrupted cache in the parser that got cleared along the way.

EDIT 2 (Thanks @LeoDabus and @MartinR): It seems that the error appears when I set an associated value to the other enum case (not the one I am comparing against - in this case, .SecondCase). I still don't understand why that triggers this compiler error in particular ("Can't use binary operator '=='..."), or what that means.

Answer

As you said in a comment, your enumeration type actually has associated values. In that case there is no default == operator for the enum type.

But you can use pattern matching even in an if statement (since Swift 2):

class MyClass {
    enum MyEnum {
        case FirstCase
        case SecondCase
        case ThirdCase(Int)
    }

    var state:MyEnum!

    func myMethod () {
        if case .FirstCase? = state {

        }
    }
}

Here .FirstCase? is a shortcut for .Some(MyEnum.FirstCase).

In your switch-statement, state is not automatically unwrapped, even if it is an implicitly unwrapped optional (otherwise you could not match against nil). But the same pattern can be used here:

switch state {
case .FirstCase?:
    // do something...
default:
    break
}