为什么UIControlState是结构而不是枚举?

piz*_*za7 3 ios swift

我对UIControlState的运行方式感到有些困惑.具体来说,如果我看下面的例子:

sender.setTitle("NewTitle", for: UIControlState.normal) 
Run Code Online (Sandbox Code Playgroud)

据我所知,这为Button的(发件人)正常状态设置了标题.我原以为.normal是UIControlState类型的Enum值,但是后来才知道它是一个带常量的结构.第一个问题:

  1. 如果目的只是为了通过一个状态,为什么这个被定义为枚举,其中.normal作为其中一个案例?

其次,当我查看UIStateControl的文档时,我看到的只是"常量"的定义,例如:

static var normal: UIControlState
Run Code Online (Sandbox Code Playgroud)

第二/第三个问题:

  1. 为什么UIStateControl的"常量"用"var"定义而不是"let?"

  2. UIControlState的静态属性如何定义为"UIControlState"类型?这不是递归的吗?

Ham*_*ish 5

为什么UIControlState是结构而不是枚举?

UIControlState根本不枚举.枚举是"OR"类型.

enum Foo {
    case a, b, c
}

var f = Foo.a
f = .b
f = .c
Run Code Online (Sandbox Code Playgroud)

所以,在上面的例子中,f可以保存.a .b .c.

但事实并非如此UIControlState; 这是一个选项集.选项集可以包含一组一个或多个案例.因此它是一个"AND"类型,我们通常使用struct符合OptionSet协议的类型来实现它们.

struct Bar : OptionSet {

    let rawValue: Int

    // Note that the raw values are unique powers of two.
    // Each bit represents a flag determining if a given case is present.
    static let a = Bar(rawValue: 1) // 001
    static let b = Bar(rawValue: 2) // 010
    static let c = Bar(rawValue: 4) // 100
}

var b = Bar.a    // .a but not .b or .c
b = [.a, .b]     // .a and .b, but not .c
b = [.c, .a, .b] // .a and .b and .c
Run Code Online (Sandbox Code Playgroud)

所以,你可以在上面的例子中看到,b可以容纳任何一组.a,.b.c.

那也是一样的UIControlState; 例如,我们可以谈论关注突出显示的控制状态:

let controlState: UIControlState = [.highlighted, .focused]
Run Code Online (Sandbox Code Playgroud)

如果它是一个enum,我们只能谈论控件是否处于一个特定状态,例如仅突出显示仅聚焦.但这不是一个正确的模型,因为控件可以同时处于多个不同的状态.

另外值得注意的是UIControlState,这个.normal案例相当于一组空的选项[]; 它表示"未突出显示或聚焦,或选择或禁用或......".

其次,当我查看UIStateControl的文档时,我看到的只是"常量"的定义,例如:

static var normal: UIControlState
Run Code Online (Sandbox Code Playgroud)

那不太准确.UIControlState自动生成的Swift标头中的声明如下所示:

public struct UIControlState : OptionSet {

    public init(rawValue: UInt)


    public static var normal: UIControlState { get }

    public static var highlighted: UIControlState { get } // used when UIControl isHighlighted is set

    public static var disabled: UIControlState { get }

    public static var selected: UIControlState { get } // flag usable by app (see below)

    @available(iOS 9.0, *)
    public static var focused: UIControlState { get } // Applicable only when the screen supports focus

    public static var application: UIControlState { get } // additional flags available for application use

    public static var reserved: UIControlState { get } // flags reserved for internal framework use
}
Run Code Online (Sandbox Code Playgroud)

你会{ get }在最后注意到.这意味着它们只是只读属性.它们的实际实现方式(作为let常量,var只读计算属性等)是一个纯粹的实现细节.

在这种情况下,UIControlState在UIKit中使用NS_OPTIONS宏定义,Swift 作为 OptionSet符合结构导入,每个选项值都是静态只读属性.

UIControlState的静态属性如何定义为"UIControlState"类型?这不是递归的吗?

不,它根本不是递归的.请记住,它们是static属性,因此只不过是命名空间的全局变量UIControlState(并且它们甚至不需要存储;它们可以被计算,但是,这又是一个实现细节).

如果它们是实例存储的属性,那么它确实是递归的.但他们不是.