在 Swift 中,UIControlState 本身并不是一个枚举,而是一个结构。来自UIControl的语言参考:
控制状态
控件的状态;一个控件在某一时刻可以有多个状态
时间。根据控件的不同,状态的识别方式也不同。为了
例如,可以配置一个 UIButton 实例(使用
setImage:forState: 方法)来显示一个图像,当它在它的
正常状态和突出显示时的不同图像。
声明
struct UIControlState : OptionSetType {
init(rawValue rawValue: UInt)
static var Normal: UIControlState { get }
static var Highlighted: UIControlState { get }
static var Disabled: UIControlState { get }
static var Selected: UIControlState { get }
static var Focused: UIControlState { get }
static var Application: UIControlState { get }
static var Reserved: UIControlState { get }
}
这里的关键是OptionSetType 协议(UIControlState 符合该协议),它允许我们对静态结构属性进行“类似枚举”的访问,因为它们有一个RawValue,即@ 987654330@。例如:
struct MyStruct : OptionSetType {
private var value: UInt
var rawValue: UInt { return self.value }
init(rawValue value: UInt) { self.value = value }
static var Normal: MyStruct { return self.init(rawValue: 1 << 0) }
static var Highlighted: MyStruct { return self.init(rawValue: 1 << 1) }
static var Disable: MyStruct { return self.init(rawValue: 1 << 2) }
// ...
}
let MyOptionsA : MyStruct = [MyStruct.Normal, MyStruct.Disable]
let MyOptionsB : MyStruct = [.Normal, .Disable]
MyOptionsB.contains(.Highlighted) // false
MyOptionsB.contains(.Normal) // true
查看符合OptionsSetType 的实例方法(参见下面的语言参考链接)。除了成员管理(如上面的.contains(...);还有.remove(...)、.insert(..)),还可以使用union(...)和intersect(...)等整洁的集合操作。
总结一下; UIButton.setImage 签名要求forState state: UIControlState 是对的,但是由于OptionSetType 协议,看起来数组的[UIControlState.Highlighted, UIControlState.Selected] 实际上是调用结构类型参数UIControlState 的有效参数。
还请注意,根据我上面的示例,结构名称可以省略,因此将 [.Highlighted, .Selected] 作为 forState 参数发送也可以。
参考和好读物: