Swift operator for substring string substitution
I am trying to set some values ββfrom a variable. The variable will have a description of the weather, and I want to ask for specific words to show different images (like sun, rain or so on) 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 strange errors.
Can a swich proposal be made with this? Or does anyone know how to do this, add an OR condition to the if clause?
source to share
Swift language has two types of operators OR
- bitwise |
(single vertical line) and boolean ||
(double vertical line). In this situation, you need a boolean OR
:
if self.descriptionWeather.description.rangeOfString("Clear") != nil || self.descriptionWeather.description.rangeOfString("clear") != nil {
self.imageWeather.image = self.soleadoImage
}
Unlike Objective-C, where you can get away with different things OR
in exchange for slightly different runtime semantics, Swift requires boolean OR
in the expression above.
source to share
I had a similar issue today and realized that this question hasn't been updated since Swift 1! This is 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
}
source to share
You can do this with a switch statement with value binding and clause where
. But first convert the string to lowercase!
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"
source to share
If you do this a lot, you can implement your own operator ~=
that matches the substring:
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)
}
}
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")
}
source to share
Continuing on Alexander's answer by implementing Marting R's suggestion in the comments, we can implement the pattern matching operator in StringProtocol. There is no need to create an additional type:
extension StringProtocol where Index == String.Index {
public static func ~= (string: Self, subSequence: SubSequence) -> Bool {
return subSequence.contains(string)
}
var subSequence: SubSequence {
return self[...]
}
}
let sentence = "Going to rain tomorrow"
switch sentence.subSequence {
case "clear":
print("Found: clear")
case "rain":
print("Found: rain") // "Found: rain\n"
case "broken clouds":
print("Found: broken clouds")
default:
print("no matches")
}
source to share
Instead, I would recommend using a dictionary as a mapping between the desired substring and the corresponding image:
func image(for weatherString: String) -> UIImage? { let imageMapping = [ "Clear": self.soleadoImage, "rain": self.soleadoImage, "broken clouds": self.nubladoImage] return imageMapping.first { weatherString.contains($0.key) }?.value }
The dictionary gives you flexibility by adding new mappings easily.
source to share