为什么我可以在没有参数的情况下初始化UIView,但是它的文档没有空的初始化程序?

时间:2016-10-10 06:24:55

标签: ios swift

let view = UIView()

是可以接受的,但唯一记录的UIView初始化程序是init(frame:CGRect)

具体来说,我正在尝试编写一个继承自UIView的新类,但此代码会抛出错误

class SquadHorizontalScrollViewCell: UIView {

    init(var: FIRDataSnapshot){
        super.init()
....

表示必须调用指定的初始化程序

5 个答案:

答案 0 :(得分:4)

UIView 继承自 UIResponder,后者继承自 NSObject

NSObject.init() initializer 可在 UIView 上访问,但不能在替换此指定初始化程序的 NSObject 的子类上访问。

让我们考虑一个例子。

class A: NSObject { 
    init(_ string: String) { } 
}

这会导致 let a = A() 的编译器错误 - 缺少初始值设定项的参数 #1,因为该初始值设定项替换了子类中 init() 的指定 NSObject 初始值设定项。

你只需要将子类的初始化器定义为一个convenience初始化器:

class A: NSObject { 
    convenience init(_ string: String) { 
        self.init() // Convenience initializers must call a designated initializer.
    } 
}

let a = A() 现在可以编译了。

UIView 还可以与子类中定义的其他指定初始化程序一起编译,因为它的指定初始化程序在编译时是未知的。根据{{​​3}},如果以编程方式实例化,则init(frame:) 为指定初始化器,否则init() 为指定初始化器。这意味着 UIView 继承了 NSObject 指定的初始化程序,而不是像上面的例子那样替换它。

在您的示例中:

class SquadHorizontalScrollViewCell: UIView {

    init(var: FIRDataSnapshot){
        super.init()

我们看到指定的初始化器是init(frame: CGRect),所以你必须调用这个指定的初始化器。

答案 1 :(得分:0)

在某个时刻,您的视图需要使用某些内容初始化,这就是编译抱怨的原因,因为它无法找到如何开始自定义视图的初始化。因为最后,视图将从xib(init(coder aDecoder: NSCoder))或框架(init(frame: CGFrame))初始化。所以在这里,最简单的方法是至少在自定义init方法中调用super.init(frame: CGRectZero)

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)
}

但你仍然需要设置框架的大小等。

答案 2 :(得分:0)

对于UIView init(frame: CGRect)是默认初始值设定项。初始化实例变量后必须调用它。如果您从NIB查看视图,则会调用init?(coder aDecoder: NSCoder)而不是init(frame: CGRect)。因此,在这种情况下,您必须在awakeFromNib()方法中初始化您的实例变量。在这种情况下,您的代码应该是这样的:

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)
    }

}

有关详细信息,请查看此链接https://developer.apple.com/reference/uikit/uiview

答案 3 :(得分:0)

指定的初始化程序应该将其超类称为初始化程序。

在这种情况下,super.init()NSObject而不是UIView的指定初始值设定项。 UIView有责任调用UIResponder init,我猜它没有指定初始值设定项,因此UIView会在其Super.init初始值设定项中调用init(frame:CGrect)。检查“初始化程序委派”

为什么let x = UIView()没问题,因为这个

  

与Objective-C中的子类不同,Swift子类不会继承   默认情况下,它们的超类初始值设定项。斯威夫特的方法阻止了   继承超类中的简单初始值设定项的情况   由一个更专业的子类,用于创建一个新的实例   未完全或正确初始化的子类。 (苹果)

因为UIView是客观的c类,它仍然可以做到。但你不能调用SquadHorizo​​ntalScrollViewCell(),除非你没有提供任何初始化程序或你覆盖超类的指定初始化程序(UIView)

检查此link以获取更多信息

答案 4 :(得分:0)

您会注意到,如果您创建自己的 UIView 子类并且仅使用日志语句覆盖 init(frame:),然后仅使用 init()、您的 init(frame:) 实例化这个新类实际上是用零大小的帧调用的。所以指定的初始化程序仍然被调用。