Use "or" logic with multiple "if case" statements

I would resort to some sort of isBar property on the enum itself, so that the "a or b" test remains readable:

enum MyEnum {
    case foo, bar(_ prop: Int)

    var isBar: Bool {
        switch self {
        case .bar: return true
        default: return false
        }
    }
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

let eitherIsBar = var1.isBar || var2.isBar

My solution for this sort of thing is:

if [var1, var2].contains(.bar) {

A lot of the time I want it the other way, a single var that might be filtered based on several values:

if [.bar, .baz].contains(var)

but indeed, if there are associated values involved you have to make them equatable and define an operator.


My guess would be that if case and guard case are syntax sugar, and just a small feature supported by compiler to improve developer’s experience. In the first case you are using consecutive conditions, which is also just a language feature to replace && operator to make the code more readable. When you are using && or || operators, the compiler would expect to get two expressions that return boolean values. case .bar = var1 itself is not exactly an expression that could live alone, without some context in Swift, so it is not treat as an expression that returns a bool.

To summarise:

  • if case and guard case are simply syntax sugar, works together with if <expression>, <expression> syntax

  • && and || are just logical operators that are basically a functions that expect two boolean arguments on both sides.

To solve your problem, use the good old switch statement. Hope it helps.


You have to implement Equatable protocol for your enum:

extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
    switch (lhs, rhs) {
        case (let .bar(prop1), let .bar(prop2)):
            return prop1 == prop2
        case (.foo, .foo):
        return true

     default:
         return false
    }
}

Then the following code should work:

if var1 == .bar(1) || var2 == .bar(1) {
    print("at least one is bar")
}

UPD: In case if you don't need to check associated value, you can do pattern matching like this:

switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}