Ios 在swift中处理UIView公共初始化
一些特殊类(如UIView)有多个指定的初始值设定项 在Objective-X中,我们可以将公共初始化分解为单独的函数Ios 在swift中处理UIView公共初始化,ios,swift,initialization,Ios,Swift,Initialization,一些特殊类(如UIView)有多个指定的初始值设定项 在Objective-X中,我们可以将公共初始化分解为单独的函数 - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { [self initialize]; } return self; } - (id)initWithFrame:(CGRect)frame { if (s
- (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;
}
在Swift中,这不再是可能的,因为以下代码导致“在super.init调用之前自行使用”
override init(frame: CGRect) {
self.initialize()
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
self.initialize()
super.init(coder: aDecoder)
}
var X : Int
override init(frame: CGRect) {
super.init(frame: frame)
self.initialize()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
将self.initial放在super.init之后也没有帮助,因为我的全部目的就是初始化成员。以下情况将导致“属性self.X未在super.init调用时初始化”
override init(frame: CGRect) {
self.initialize()
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
self.initialize()
super.init(coder: aDecoder)
}
var X : Int
override init(frame: CGRect) {
super.init(frame: frame)
self.initialize()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
如果我想在这种情况下考虑公共初始化,我应该怎么做?请注意,我特别不想使用awakeFromNib,因为我希望我的对象在对象层次结构中的任何相关awakeFromNib实现中都可用。还要注意,选项对我的用例没有意义。最明显的答案是在调用
super.init
之后调用initialize
:
override init(frame: CGRect) {
super.init(frame: frame)
self.initialize()
}
但是,您可能需要在initialize
方法中初始化一些实例变量。事实是:
super
之前,必须初始化所有成员变量super.init
之前,不能调用self
上的方法(或访问self
上的计算属性)initialize
中初始化的实例变量,则必须使用var
声明每个此类变量,而不是let
,并执行以下操作之一:
var name: String = "Fred"
设置为可选
,并将其初始化为nil:
var name: String?
var name: String!
隐式地设置为appedoptional
,并将其初始化为nil:
var name: String?
var name: String!
在这一点上,我的偏好是#2(将其设置为
可选,并初始化为nil)。这里有一个简洁的解决方案:
基本上,标记两个init函数便利性
,然后让它们调用第三个私有
init函数,该函数具有您的通用初始化代码
对于您的情况,您可以使用以下内容:
class MyView: UIView {
let X: Int // No need to use an optional, as we assign this in an initializer
enum InitMethod {
case Coder(NSCoder)
case Frame(CGRect)
}
override convenience init(frame: CGRect) { // Marking as convenience let's us call out to another constructor
self.init(.Frame(frame))!
}
required convenience init?(coder aDecoder: NSCoder) { // Marking as convenience let's us call out to another constructor
self.init(.Coder(aDecoder))
}
private init?(_ initMethod: InitMethod) {
// You can put your common initialization code here:
X = 1
switch initMethod {
case let .Coder(coder): super.init(coder: coder)
case let .Frame(frame): super.init(frame: frame)
}
}
}
这是针对我想要一个非可选变量的情况。在这种情况下,唯一的解决方案似乎是使用默认值。然而,这并不包括违约之间相互依存的情况。例如,如果我有一个非可选Y,它取决于非可选X的默认值是什么?实例变量的初始值设定项表达式(在变量声明中)不能引用self
、任何其他实例变量或任何init
参数。事情就是这样。是的,它很糟糕。所以,如果你想使用非可选的,某些功能是根本不可能的。您必须调整您的类型选择,使之成为您从未真正想要的,只是为了与语言限制保持一致。这些情况的存在也意味着,有时候,在重构或添加功能时,您需要将非可选项更改为可选项,以使其正常工作。因此,在这种情况下,人们最终只会使用optionals,即使是那些总是有保证的东西。就像我说的,这很糟糕。好吧,你能在你的答案中添加关于它如何糟糕的部分,然后我会接受它。基本上,答案是对于所提到的用例没有很好的答案。请为这个特定的问题提供一个解决方案