在swift中处理UIView常见初始化

gra*_*ley 6 initialization ios swift

像UIView这样的特殊类有多个指定的初始化程序.

在Objective-X中,我们可以将常见初始化分解为单独的函数

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self initialize];
    }

    return self;
}

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initialize];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

在Swift中,这不再是一种可能性,因为以下代码会导致"在super.init调用之前自行使用"

override init(frame: CGRect) {
    self.initialize()
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
    self.initialize()
    super.init(coder: aDecoder)
}
Run Code Online (Sandbox Code Playgroud)

在super.init之后放置self.initialize也没有帮助,因为我的整个目的是初始化成员.以下将导致'属性self.X未在super.init调用时初始化'

var X : Int

override init(frame: CGRect) {
    super.init(frame: frame)
    self.initialize()
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.initialize()
}
Run Code Online (Sandbox Code Playgroud)

如果我想在这种情况下考虑常见的初始化,我该怎么办?请注意,我特别不想使用awakeFromNib,因为我希望我的对象在我的对象层次结构中的任何相关awakeFromNib实现中可用.另请注意,选项对我的用例没有意义.

rob*_*off 2

显而易见的答案是initialize在调用后调用super.init

override init(frame: CGRect) {
    super.init(frame: frame)
    self.initialize()
}
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望在initialize方法中初始化一些实例变量。事实是这样的:

  1. 调用之前必须初始化所有成员变量super
  2. 在调用 之前,您不能调用 上的方法self(或访问 上的计算属性selfsuper.init

不可避免的结论是,如果您想要在 中初始化实例变量initialize,则必须使用var、 not声明每个此类变量let,并执行以下操作之一:

  1. 给实例变量一个默认值:

    var name: String = "Fred"
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建实例变量Optional,并将其初始化为 nil:

    var name: String?
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建实例变量ImplicitlyUnwrappedOptional,并将其初始化为 nil:

    var name: String!
    
    Run Code Online (Sandbox Code Playgroud)

我此时的偏好是#2(创建它Optional并初始化为nil)。