Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift switch statement for matching substrings of a String

Im trying to ask for some values from a variable. The variable is going to have the description of the weather and i want to ask for specific words in order to show different images (like a sun, rain or so) The thing is i have code like this:

    if self.descriptionWeather.description.rangeOfString("Clear") != nil
{
    self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("rain") != nil
{
    self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("broken clouds") != nil
{
    self.imageWeather.image = self.nubladoImage
}

Because when i tried to add an "OR" condition xcode gives me some weird errors.

Is it possible to do a swich sentence with that? Or anyone knows how to do add an OR condition to the if clause?

like image 960
LPS Avatar asked Sep 30 '14 02:09

LPS


5 Answers

I had a similar problem today and realized this question hasn't been updated since Swift 1! Here's how I solved it in Swift 4:

switch self.descriptionWeather.description {
case let str where str.contains("Clear"):
    print("clear")
case let str where str.contains("rain"):
    print("rain")
case let str where str.contains("broken clouds"):
    print("broken clouds")
default:
    break
}
like image 180
Jenny Avatar answered Oct 08 '22 11:10

Jenny


Swift 5 Solution

func weatherImage(for identifier: String) -> UIImage? {
    switch identifier {
    case _ where identifier.contains("Clear"),
         _ where identifier.contains("rain"):
        return self.soleadoImage
    case _ where identifier.contains("broken clouds"):
        return self.nubladoImage
    default: return nil
    }
}
like image 37
Lal Krishna Avatar answered Oct 08 '22 10:10

Lal Krishna


You can do this with a switch statement using value binding and a where clause. But convert the string to lowercase first!

var desc = "Going to be clear and bright tomorrow"

switch desc.lowercaseString as NSString {
case let x where x.rangeOfString("clear").length != 0:
    println("clear")
case let x where x.rangeOfString("cloudy").length != 0:
    println("cloudy")
default:
    println("no match")
}

// prints "clear"
like image 13
Nate Cook Avatar answered Oct 08 '22 11:10

Nate Cook


Swift language has two kinds of OR operators - the bitwise ones | (single vertical line), and the logical ones || (double vertical line). In this situation you need a logical OR:

if self.descriptionWeather.description.rangeOfString("Clear") != nil || self.descriptionWeather.description.rangeOfString("clear") != nil {
    self.imageWeather.image = self.soleadoImage
}

Unlike Objective-C where you could get away with a bitwise OR in exchange for getting a slightly different run-time semantic, Swift requires a logical OR in the expression above.

like image 5
Sergey Kalinichenko Avatar answered Oct 08 '22 10:10

Sergey Kalinichenko


If you do this a lot, you can implement a custom ~= operator that defines sub-string matching. It lends itself to this nice syntax:

switch "abcdefghi".substrings {
    case "def": // calls `"def" ~= "abcdefghi".substrings`
        print("Found substring: def") 
    case "some other potential substring":
        print("Found \"some other potential substring\"")
    default: print("No substring matches found")
}

Implementation:

import Foundation

public struct SubstringMatchSource {
    private let wrapped: String
    
    public init(wrapping wrapped: String) {
        self.wrapped = wrapped
    }
    
    public func contains(_ substring: String) -> Bool {
        return self.wrapped.contains(substring)
    }
    
    public static func ~= (substring: String, source: SubstringMatchSource) -> Bool {
        return source.contains(substring)
    }
}

extension String {
    var substrings: SubstringMatchSource {
        return SubstringMatchSource(wrapping: self)
    }
}
like image 4
Alexander Avatar answered Oct 08 '22 11:10

Alexander