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"]