Swift if case with logical OR - swift

Say we have an enum:
enum MyEnum {
case foo(Int)
case bar
}
and we can do something like this:
func myFunc(_ foo: MyEnum, _ bar: MyEnum) {
if case .foo(_) = foo, case .bar = bar {...}
}
but what if I need some like this
if case .foo(_) = foo, case .bar = bar OR someVar == true {...}
where I want either case .foo(_) = foo, case .bar = bar to be true, or someVar to be true.
Apparently I can't put || there, and I couldn't figure out an alternative. Am I missing something simple?

I'm not sure if this is possible with a single if statement. However, you could use a switch statement like this:
enum MyEnum {
case foo(Int)
case bar
}
func myFunc(_ foo: MyEnum, _ bar: MyEnum, _ someVar: Bool) {
switch (foo, bar, someVar) {
case (.foo, .bar, _), (_, _, true):
break
default:
break
}
}

Related

How can I stop repeating code for accessing value of associated type enum?

I want to access to value of my enum in case, I made a switch for getting access to value, but as you can see I am reaping my codes, how can i do this in better way?
enum TestEnum {
case a(value: Int)
case b(value: Int)
case c(value: Int)
var value: Int {
switch self {
case .a(let value):
return value
case .b(let value):
return value
case .c(let value):
return value
}
}
}
Maybe you could change the way your data is modeled
struct MyStruct {
enum Kind {
case one, two, three
}
let kind: Kind
let value: Int
}
var value: Int {
switch self {
case .a(let value),
.b(let value),
.c(let value):
return value
}
}

Swift compiling of multiple switch case fallthroughs and the same named associated value is unstable and often crashes

Swift compiler often crashes with multiple (>=2) switch case fallthroughs and the same named associated value. The following code doesn't compile for Swift version 4.2:
enum Foo {
case a(count: Int)
case b(count: Int)
case c(count: Int)
case d
}
func bar(v: Foo) {
switch v {
case .a(let count): fallthrough
case .b(let count): fallthrough
case .c(let count):
print(count)
case .d: break
}
}
bar(v: .a(count: 4))
Bug report submitted at: https://bugs.swift.org/browse/SR-9729
I'm not sure if Swift permits fallthrough with value-binding.
But this surely works:
func bar(v: Foo) {
switch v {
case .a(let count),
.b(let count),
.c(let count):
print(count)
case .d: break
}
}
Workaround:
enum Foo {
case a(count: Int)
case b(count: Int)
case c(count: Int)
case d
var count: Int {
if case .a(let count) = self {
return count
} else if case .b(let count) = self {
return count
} else if case .c(let count) = self {
return count
} else {
fatalError()
}
}
}
func bar(v: Foo) {
switch v {
case .a: fallthrough
case .b: fallthrough
case .c:
print(v.count)
case .d: break
}
}
bar(v: .a(count: 4))

Enum with associated value as associated value of another enum (nested associated value)

I have enum Foo with associated value. Enum Foo serves as an associated value of another enum, Car. I would like to know how to access the 'nested' associated value of Foo, as shown in the example below:
enum Foo: Equatable {
case moo
case zoo(String)
}
enum Car {
case mar
case dar(Foo)
case gar(Foo)
}
func request(with type: Car) -> String {
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case .dar(let foo) where foo == .zoo(let value):
// how can I access the associated value of foo?
// This where syntax results in an error - Consecutive statements on a line must be separated by ';'
}
}
You can use pattern matching:
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case .dar(.moo):
return "dar: moo"
case let .dar(.zoo(value)):
return "dar: \(value)"
case .gar:
return "gar"
}
Or, if you want to handle Foo in the same manner for dar and gar, you can bind foo in one case:
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case let .dar(foo), let .gar(foo):
switch foo {
case .moo:
return "moo"
case let .zoo(value):
return value
}
}
As you rightly say, it's nested. So nest! Use a switch within the switch. This compiles:
func request(with type: Car) -> String {
switch type {
case .mar:
return "mar"
case .dar(let foo):
switch foo {
case .moo: return "darmoo"
case .zoo(let s): return s
}
case .gar:
return "gar"
}
}

Can I use a cast in a case pattern?

I have a switch case statement over an enum type with associated values in Swift:
enum Foo {
case Something(let s: Any)
// …
}
I would like to use a cast in the pattern match, a bit like this:
let foo: Foo = // …
switch foo {
case .Something(let a as? SpecificType):
// …
}
In other words, I would like the case pattern to succeed only if the cast succeeds. Is that possible?
Your example basically works as is:
enum Foo {
case Something(s: Any)
}
let foo = Foo.Something(s: "Success")
switch foo {
case .Something(let a as String):
print(a)
default:
print("Fail")
}
If you replace "Success" with e.g. the number 1 it will print "Fail" instead. Is that what you want?
You can use where clause:
enum Foo {
case Something(s: Any)
}
let foo: Foo = Foo.Something(s: "test")
switch foo {
case .Something(let a) where a is String:
print("Success")
default:
print("Failed")
}

Swift: Test class type in switch statement

In Swift you can check the class type of an object using 'is'. How can I incorporate this into a 'switch' block?
I think it's not possible, so I'm wondering what is the best way around this.
You absolutely can use is in a switch block. See "Type Casting for Any and AnyObject" in the Swift Programming Language (though it's not limited to Any of course). They have an extensive example:
for thing in things {
switch thing {
case 0 as Int:
println("zero as an Int")
case 0 as Double:
println("zero as a Double")
case let someInt as Int:
println("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
println("a positive double value of \(someDouble)")
// here it comes:
case is Double:
println("some other double value that I don't want to print")
case let someString as String:
println("a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
println("an (x, y) point at \(x), \(y)")
case let movie as Movie:
println("a movie called '\(movie.name)', dir. \(movie.director)")
default:
println("something else")
}
}
Putting up the example for "case is - case is Int, is String:" operation, where multiple cases can be used clubbed together to perform the same activity for Similar Object types. Here "," separating the types in case is operating like a OR operator.
switch value{
case is Int, is String:
if value is Int{
print("Integer::\(value)")
}else{
print("String::\(value)")
}
default:
print("\(value)")
}
Demo Link
In case you don't have a value, just any object:
swift 4
func test(_ val:Any) {
switch val {
case is NSString:
print("it is NSString")
case is String:
print("it is a String")
case is Int:
print("it is int")
default:
print(val)
}
}
let str: NSString = "some nsstring value"
let i:Int=1
test(str)
// it is NSString
test(i)
// it is int
I like this syntax:
switch thing {
case _ as Int: print("thing is Int")
case _ as Double: print("thing is Double")
}
since it gives you the possibility to extend the functionality fast, like this:
switch thing {
case let myInt as Int: print("\(myInt) is Int")
case _ as Double: print("thing is Double")
}