Swift具有OptionSet类型,它基本上将集合操作添加到C样式位标志. Apple在他们的框架中广泛使用它们.示例包括animate中的options参数(withDuration:delay:options:animations:completion :).
从好的方面来说,它可以让你使用干净的代码:
- options: [.allowAnimatedContent,.curveEaseIn]
然而,也有一个缺点.
如果我想显示OptionSet的指定值,似乎没有一个干净的方法来做它:
- let options: UIViewAnimationOptions = [.allowAnimatedContent,.curveEaseIn]
- print("options = " + String(describing: options))
显示非常无用的消息:
options = UIViewAnimationOptions(rawValue: 65664)
其中一些位字段的文档将常量表示为二次幂值:
- flag0 = Flags(rawValue: 1 << 0)
但是我的示例OptionSet UIViewAnimationOptions的文档并未告诉您有关这些标志的数值的任何信息,并且从十进制数中计算出的位数并不简单.
题:
是否有一些干净的方法将OptionSet映射到选定的值?
我想要的输出将是这样的:
options = UIViewAnimationOptions([.allowAnimatedContent,.curveEaseIn])
但是,如果没有一堆杂乱的代码需要我为每个标志维护一个显示名称表,我想不出办法做到这一点.
解决方法
这是我采用的一种方法,使用字典并迭代键.不是很好,但它确实有效.
- struct MyOptionSet: OptionSet,Hashable,CustomStringConvertible {
- let rawValue: Int
- static let zero = MyOptionSet(rawValue: 1 << 0)
- static let one = MyOptionSet(rawValue: 1 << 1)
- static let two = MyOptionSet(rawValue: 1 << 2)
- static let three = MyOptionSet(rawValue: 1 << 3)
- var hashValue: Int {
- return self.rawValue
- }
- static var debugDescriptions: [MyOptionSet:String] = {
- var descriptions = [MyOptionSet:String]()
- descriptions[.zero] = "zero"
- descriptions[.one] = "one"
- descriptions[.two] = "two"
- descriptions[.three] = "three"
- return descriptions
- }()
- public var description: String {
- var result = [String]()
- for key in MyOptionSet.debugDescriptions.keys {
- guard self.contains(key),let description = MyOptionSet.debugDescriptions[key]
- else { continue }
- result.append(description)
- }
- return "MyOptionSet(rawValue: \(self.rawValue)) \(result)"
- }
- }
- let myOptionSet = MyOptionSet([.zero,.one,.two])
- // prints MyOptionSet(rawValue: 7) ["two","one","zero"]