let view = UIView()
Why does this compile without an error when the only documented UIView
initializer is init(frame: CGRect)
?
Specifically, I am trying to write a new class that inherits from UIView
, but this code throws an error:
class SquadHorizontalScrollViewCell: UIView {
init(var: FIRDataSnapshot){
super.init()
....
It says it must call a designated initializer.
UIView
inherits from UIResponder
which inherits from NSObject
.
The NSObject.init()
initializer is accessible on UIView
, but not on subclasses of NSObject
which replace this designated initializer.
Let's consider an example.
class A: NSObject {
init(_ string: String) { }
}
This leads to a compiler error for let a = A()
- missing argument #1 for initializer because this initializer replaces the designated init()
initializer for NSObject
in the subclass.
You just need to define the initializer of the subclass as a convenience
initializer:
class A: NSObject {
convenience init(_ string: String) {
self.init() // Convenience initializers must call a designated initializer.
}
}
let a = A()
now compiles.
UIView
can also compile with other designated initializers defined in the subclass, since its designated initializer is not known at compile time. As per the docs, if instantiating programmatically, init(frame:)
is the designated initializer, otherwise init()
is the designated initializer. This means that UIView
inherits the NSObject
designated initializer rather than replacing it as in the above example.
In your example:
class SquadHorizontalScrollViewCell: UIView {
init(var: FIRDataSnapshot){
super.init()
We see that the designated initializer is init(frame: CGRect)
, so you have to call this designated initializer instead.
A designated initializer should call its superclass designated initializer.
In this case super.init()
is the designated initializer of NSObject
not UIView
.
It would be UIView's responsibility to call UIResponder init ,I guess it has no designated initializer, hence UIView will call Super.init
in its init(frame:CGrect)
initializer. check "Initializer Delegation"
for why let x = UIView()
is ok , its because of this
Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized. (Apple)
since UIView is objective c class it still can do it. but you won't be able to call SquadHorizontalScrollViewCell() unless you did not provide any initializer or you overrides the designated initializer of the superclass (UIView)
Check this link for more info
For UIView
init(frame: CGRect)
is default initializer. You must call it after initialize your instance variable. If you take view from NIB
then init?(coder aDecoder: NSCoder)
is called instead of init(frame: CGRect)
. So in that case you have to initialize your instance variable in awakeFromNib()
method. In this case your code should be like this:
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)
}
}
For more info you can check this link https://developer.apple.com/reference/uikit/uiview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With