这导致let a = A()的编译器错误-缺少初始化器的参数#1,因为这个初始化器替换了子类中NSObject的指定init()初始化器。 您只需要将子类的初始化式定义为convenience初始化式:
class A: NSObject {
convenience init(_ string: String) {
self.init() // Convenience initializers must call a designated initializer.
}
}
let a = A()现在可以编译。 UIView也可以与子类中定义的其他指定初始化器一起编译,因为它的指定初始化器在编译时是未知的。根据docs,如果以编程方式示例化,则init(frame:)是指定初始化器,否则init()是指定的初始化器。这意味着UIView继承了NSObject指定的初始化器,而不是像上面的例子那样替换它。 在您的示例中:
class SquadHorizontalScrollViewCell: UIView {
init(var: FIRDataSnapshot){
super.init()
class SquadHorizontalScrollViewCell: UIView {
init(firDataSnapshot: FIRDataSnapshot){
// intialize your instance variable
super.init(frame: CGRectZero) // set your expected frame. For demo I have set `CGRectZero`
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
init (var: FIRDataSnapshot) {
super.init(frame: CGRectZero)
}
// This method below is always needed when you want to override your init method
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
6条答案
按热度按时间nkkqxpd91#
UIView
继承自UIResponder
,而UIResponder
继承自NSObject
。NSObject.init()
initializer可以在UIView
上访问,但不能在NSObject
的子类上访问,这些子类替换了这个指定的初始化器。让我们考虑一个例子。
这导致
let a = A()
的编译器错误-缺少初始化器的参数#1,因为这个初始化器替换了子类中NSObject
的指定init()
初始化器。您只需要将子类的初始化式定义为
convenience
初始化式:let a = A()
现在可以编译。UIView
也可以与子类中定义的其他指定初始化器一起编译,因为它的指定初始化器在编译时是未知的。根据docs,如果以编程方式示例化,则init(frame:)
是指定初始化器,否则init()
是指定的初始化器。这意味着UIView
继承了NSObject
指定的初始化器,而不是像上面的例子那样替换它。在您的示例中:
我们看到指定的初始化器是
init(frame: CGRect)
,所以你必须调用这个指定的初始化器。jckbn6z72#
指定的初始化器应该调用它的超类指定的初始化器。
在这种情况下,
super.init()
是NSObject
的指定初始化器,而不是UIView
。调用UIResponder init是UIView的责任,我猜它没有指定的初始化器,因此UIView将在其init(frame:CGrect)
初始化器中调用Super.init
。检查“初始化器委派”为什么
let x = UIView()
是可以的,这是因为与Objective-C中的子类不同,Swift子类默认情况下不会继承它们的超类初始化器。Swift的方法防止了这样一种情况,即超类中的简单初始化器被更专门的子类继承,并用于创建未完全或正确初始化的子类的新示例。
由于UIView是目标c类,它仍然可以这样做。但您将无法调用SquadHorizontalScrollViewCell(),除非您没有提供任何初始化器或您覆盖了超类(UIView)的指定初始化器
查看此link了解更多信息
rqcrx0a63#
对于
UIView
,init(frame: CGRect)
是默认的初始化器。你必须在初始化你的示例变量之后调用它。如果你从NIB
获取视图,那么init?(coder aDecoder: NSCoder)
被调用而不是init(frame: CGRect)
。所以在这种情况下,你必须在awakeFromNib()
方法中初始化你的示例变量。在这种情况下,你的代码应该是这样的:欲了解更多信息,请查看此链接https://developer.apple.com/reference/uikit/uiview
hyrbngr74#
在某个时候,你的视图需要初始化一些东西,这就是为什么编译会抱怨,因为它找不到如何开始初始化你的自定义视图。因为在最后,一个视图将从一个xib(
init(coder aDecoder: NSCoder)
),或从一个frame(init(frame: CGFrame)
)初始化。所以这里,最简单的方法是至少在你的自定义init方法中调用super.init(frame: CGRectZero)
。但你仍然需要设置你的框架的大小等。
mxg2im7a5#
你会注意到,如果你创建了自己的
UIView
子类,只使用log语句覆盖init(frame:)
,然后只使用init()
示例化这个新类,你的init(frame:)
实际上是用一个零大小的框架调用的。所以指定的初始化器仍然会被调用。kqhtkvqz6#
我想补充一点,如果你在Swift中实现了UIView的一个子类,并且没有提供
init(frame:)
初始化器,那么在运行时会抛出一个异常:当你添加如下所示的初始化器时,你会得到一个有趣的日志输出:
输出:
基本上会调用两个初始化器,第二个初始化器会覆盖第一个初始化器设置的任何值。不要调用
super.init()
,而是调用super.init(frame: .zero)
来纠正这个问题。