Travis Griggs Travis Griggs - 6 months ago 29
Swift Question

more idiomatic swift test for optionset?

Still getting used to the use of

OptionSetType
in Swift.

In good ol' C, if I had something like

typedef enum {
CHAR_PROP_BROADCAST =0x01,
CHAR_PROP_READ =0x02,
CHAR_PROP_WRITE_WITHOUT_RESP =0x04,
CHAR_PROP_WRITE =0x08,
CHAR_PROP_NOTIFY =0x10,
CHAR_PROP_INDICATE =0x20,
CHAR_PROP_SIGNED_WRITE =0x40,
CHAR_PROP_EXT =0x80
} CharacteristicProperty;


I could test a set of flags with something simple like:

if ((propertiesMask & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) != 0) ...


The Swift alternative might look like

let properties:CBCharacteristicProperties = [.Write, .Read, .Indicate]
!properties.intersect([.Indicate, .Notify]).isEmpty


Is there a more idiomatic way to do this test? Not a fan of the ! out front. But otherwise, seems straightforward enough, except I'm really interested in when there IS an intersection. This led me to want to add my own.

extension OptionSetType {
func hasIntersection(other:Self) -> Bool {
return !self.intersect(other).isEmpty
}
}


Which then allows me to write

properties.hasIntersection([.Indicate, .Notify])


Is there a better/more idiomatic way to do this? Did I roll my own and miss something?

Answer

There's this method from the protocol SetAlgebraType which OptionSetType implements:

isDisjointWith(_: Self) -> Bool

Returns true iff self.intersect(other).isEmpty.

So you could shorten your test to:

!properties.isDisjointWith([.Indicate, .Notify])

or

properties.isDisjointWith([.Indicate, .Notify]) == false

You can also compare the raw values with bitwise operators, just as you would do in C:

(properties.rawValue & (CharacteristicProperties.Notify.rawValue | CharacteristicProperties.Indicate.rawValue)) != 0

Full example code (in a playground):

struct CBCharacteristicProperties : OptionSetType {
  let rawValue: UInt
  init(rawValue: UInt) { self.rawValue = rawValue }

  static let Broadcast          = CBCharacteristicProperties(rawValue:0x01)
  static let Read               = CBCharacteristicProperties(rawValue:0x02)
  static let WriteWithoutResp   = CBCharacteristicProperties(rawValue:0x04)
  static let Write              = CBCharacteristicProperties(rawValue:0x08)
  static let Notify             = CBCharacteristicProperties(rawValue:0x10)
  static let Indicate           = CBCharacteristicProperties(rawValue:0x20)
  static let SignedWrite        = CBCharacteristicProperties(rawValue:0x40)
  static let Ext                = CBCharacteristicProperties(rawValue:0x80)
}

let properties = CBCharacteristicProperties([.Write, .Read, .Indicate])
print(!properties.intersect([.Indicate, .Notify]).isEmpty)
print(!properties.isDisjointWith([.Indicate, .Notify]))
print(properties.isDisjointWith([.Indicate, .Notify]) == false)
print((properties.rawValue & (CBCharacteristicProperties.Notify.rawValue | CBCharacteristicProperties.Indicate.rawValue)) != 0)

result:

"true"
"true"
"true"
"true"
Comments