How to Test an Optionset with a Switch Statement

Switch to match multiple cases from OptionSetType

OptionSetType is a subtype of SetAlgebraType, so you can use set algebra methods to test one combination of options against another. Depending on exactly what you want to ask (and what the sets in question are), there may be multiple ways to do it.

First, I'll put the attributes I'm querying for in a local constant:

let youngBoy: Person = [.Young, .Boy] 

Now, to use that for one kind of test that works well:

if him.isSupersetOf(youngBoy) {
// go to Toshi station, pick up power converters
}

Of course, what this is specifically asking is whether him contains all the options listed in youngBoy. That might be all you care about, so that's just fine. And it's also safe if you later extend Person to have other options, too.

But what if Person had other possible options, and you wanted to assert that him contains exactly the options listed in youngBoy, and no others? SetAlgebraType extends Equatable, so you can just test with ==:

if him == youngBoy {
// he'd better have those units on the south ridge repaired by midday
}

By the way, you don't want to use a switch statement for this. Switch is for selecting one out of several possible cases (is it A or B?), so using it to test combinatorics (is it A, B, A and B, or neither?) makes your code unwieldy.

OptionSet with associated value for each option

But that does not compile. In fact, it looks like the filter property is not separately defined for each option, but rather for a whole option set.

This is because an OptionSet isn't really a set, per se. If I have the following OptionSet:

struct MyOptions: OptionSet {
let rawValue: Int

static let foo = MyOptions(1 << 0)
static let bar = MyOptions(1 << 1)
}

and then I make the set like so:

let opts: MyOptions = [.foo, .bar]

I don't actually have a collection with two MyOptions instances in it. Instead, I have a new instance of MyOptions whose rawValue is set to (.foo.rawValue | .bar.rawValue)—i.e. 3. The original two MyOptions instances are discarded as soon as opts is made.

Similarly, your logger.outputs will be an instance of OutputOptions with rawValue 3 and the default value for filter.

Thus, it's not really possible to do what you want with an OptionSet.

Swift: testing against optional value in switch case

Optional is just a enum like this:

enum Optional<T> : Reflectable, NilLiteralConvertible {
case none
case some(T)

// ...
}

So you can match them as usual "Associated Values" matching patterns:

let someValue = 5
let someOptional: Int? = nil

switch someOptional {
case .some(someValue):
println("the value is \(someValue)")
case .some(let val):
println("the value is \(val)")
default:
println("nil")
}

If you want match from someValue, using guard expression:

switch someValue {
case let val where val == someOptional:
println(someValue)
default:
break
}

And for Swift > 2.0

switch someValue {
case let val where val == someOptional:
print("matched")
default:
print("didn't match; default")
}

retrieve the value selected in optionset field and display ita value in a text field

For getting the option set value:

int value = ((OptionSetValue)entity["yourattributename"]).Value;

For getting the text:

String text = entity.FormattedValues["yourattributename"].ToString();

In the above code entity is the Entity object from which the optionset value/text to be retrieved. Please replace the attribute name with your case.

New to Swift and I am stuck on whether or not to use a switch or if statement

The switch argument is wrong, you have to switch on a tuple like in mixColors:

switch (firstSelection, secondSelection) {

case (0, 0):

...

}

Create a OptionSet that is usable with IBInspectable

So I did find a way to be able to use it by writing some sort of adapter.

I'm pretty sure it can be done better and if anyone has a way to do so don't hesitate to provide your solution but this is how I did it right now

public struct Corners: OptionSet {
private enum Corner: Int, CustomStringConvertible {
case TopLeft=1
case TopRight=2
case BottomLeft=4
case BottomRight=8
case All=16

public var description: String {
var shift = 0
while (rawValue.hashValue >> shift != 1) { shift += 1 }
return ["topleft", "topright", "bottomleft", "bottomright", "all"][shift]
}
}
public let rawValue: Int
public init(rawValue: Int) { self.rawValue = rawValue }
private init(_ shape: Corner) { self.rawValue = shape.rawValue }

static let TopLeft = Corners(Corner.TopLeft)
static let TopRight = Corners(Corner.TopRight)
static let BottomLeft = Corners(Corner.BottomLeft)
static let BottomRight = Corners(Corner.BottomRight)
static let All = [TopLeft, TopRight, BottomLeft, BottomRight]
}

// Needed to split the string that's provided in the @IBInspectable. and remove any possible spaces the user introduced
extension String {
func getStrings() -> [String] {
var stringArray: [String] = []
let strings = self.characters.split{$0 == ","}.map(String.init)
for s in strings {
let string = s.removeSpaces()
stringArray.append(string)
}
return stringArray
}

func removeSpaces() -> String {
if self.characters.first == " " {
var copy = self
copy.characters.removeFirst()
return copy.removeSpaces()
} else {
return self
}
}
}

Then my @IBInspectable looks like this

var corners = [Corners.TopLeft]
@IBInspectable public var onCorners: String = "" {
willSet {
corners = []
for s in newValue.lowercased().getStrings() {
switch s {
case "topleft":
corners.append(Corners.TopLeft)
case "topright":
corners.append(Corners.TopRight)
case "bottomleft":
corners.append(Corners.BottomLeft)
case "bottomright":
corners.append(Corners.BottomRight)
case "all":
corners = Corners.All
default:
return
}
}
}
didSet {
// Do your logic here
}
}


Related Topics



Leave a reply



Submit