Say I want to init
a UIView
subclass with a String
and an Int
.
How would I do this in Swift if I'm just subclassing UIView
? If I just make a custom init()
function but the parameters are a String and an Int, it tells me that "super.init() isn't called before returning from initializer".
And if I call super.init()
I'm told I must use a designated initializer. What should I be using there? The frame version? The coder version? Both? Why?
This question is related to
ios
swift
cocoa-touch
uiview
instantiation
I create a common init for the designated and required. For convenience inits I delegate to init(frame:)
with frame of zero.
Having zero frame is not a problem because typically the view is inside a ViewController's view; your custom view will get a good, safe chance to layout its subviews when its superview calls layoutSubviews()
or updateConstraints()
. These two functions are called by the system recursively throughout the view hierarchy. You can use either updateContstraints()
or layoutSubviews()
. updateContstraints()
is called first, then layoutSubviews()
. In updateConstraints()
make sure to call super last. In layoutSubviews()
, call super first.
Here's what I do:
@IBDesignable
class MyView: UIView {
convenience init(args: Whatever) {
self.init(frame: CGRect.zero)
//assign custom vars
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
commonInit()
}
private func commonInit() {
//custom initialization
}
override func updateConstraints() {
//set subview constraints here
super.updateConstraints()
}
override func layoutSubviews() {
super.layoutSubviews()
//manually set subview frames here
}
}
You can try out this implementation for running Swift 5 on XCode 11
class CustomView: UIView {
var customParam: customType
var container = UIView()
required init(customParamArg: customType) {
self.customParam = customParamArg
super.init(frame: .zero)
// Setting up the view can be done here
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupView() {
// Can do the setup of the view, including adding subviews
setupConstraints()
}
func setupConstraints() {
// setup custom constraints as you wish
}
}
Here is how I do it on iOS 9 in Swift -
import UIKit
class CustomView : UIView {
init() {
super.init(frame: UIScreen.mainScreen().bounds);
//for debug validation
self.backgroundColor = UIColor.blueColor();
print("My Custom Init");
return;
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented"); }
}
Here is a full project with example:
Here is how I do a Subview on iOS in Swift -
class CustomSubview : UIView {
init() {
super.init(frame: UIScreen.mainScreen().bounds);
let windowHeight : CGFloat = 150;
let windowWidth : CGFloat = 360;
self.backgroundColor = UIColor.whiteColor();
self.frame = CGRectMake(0, 0, windowWidth, windowHeight);
self.center = CGPoint(x: UIScreen.mainScreen().bounds.width/2, y: 375);
//for debug validation
self.backgroundColor = UIColor.grayColor();
print("My Custom Init");
return;
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented"); }
}
Source: Stackoverflow.com