Reputation: 7096
Suppose I have an enum case with an associated value, and two variables of that enum type:
enum MyEnum {
case foo, bar(_ prop: Int)
}
let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)
If I want to check if both variables match the general case with the associated value, I can do that with a comma:
if case .bar = var1, case .bar = var2 {
print("both are bar")
}
But I need to check if either matches the case, with something like this:
if case .bar = var1 || case .bar = var2 {
print("at least one is bar")
}
However, that doesn't compile. Is there another way to write this to make the logic work?
Upvotes: 34
Views: 17574
Reputation: 1026
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.
Upvotes: 13
Reputation: 17844
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
Upvotes: 18
Reputation: 9593
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
}
Upvotes: 9
Reputation: 4239
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.
Upvotes: 6