如何在 Swift 中为 UIView 子类编写自定义 init?

假设我想要 init一个具有 StringIntUIView子类。

如果我只是子类化 UIView,我如何在 Swift 中做到这一点?如果我只创建一个自定义的 init()函数,但是参数是 String 和 Int,那么它告诉我“在从初始化器返回之前没有调用 super.init ()”。

如果我调用 super.init(),我被告知必须使用指定的初始化程序。我应该在那里使用什么?相框版本?程序员版本?两个都是?为什么?

141157 次浏览

init(frame:)版本是默认的初始值设定项。只有在初始化实例变量之后才能调用它。如果这个视图是从 Nib 重新构造的,那么您的自定义初始值设定项将不会被调用,而是调用 init?(coder:)版本。由于 Swift 现在需要实现所需的 init?(coder:),因此我更新了下面的示例,并将 let变量声明更改为 var和可选。在这种情况下,您可以在 awakeFromNib()中或在以后的某个时间初始化它们。

class TestView : UIView {
var s: String?
var i: Int?
init(s: String, i: Int) {
self.s = s
self.i = i
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
}


required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

以下是我在 iOS9上用 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"); }
}

下面是一个完整的项目和例子:

以下是我如何在 Swift-iOS 上做一个 Subview

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

我为指定的和必需的。为了方便,inits 我委托给 init(frame:)的帧为零。

零帧不是问题,因为视图通常位于 ViewController 的视图中; 当其超视图调用 layoutSubviews()updateConstraints()时,您的自定义视图将获得一个很好的、安全的机会来布局其子视图。系统在整个视图层次结构中递归地调用这两个函数。您可以使用 updateContstraints()layoutSubviews()。先调用 updateContstraints(),然后调用 layoutSubviews()。在 updateConstraints()中一定要调用 super 最后。在 layoutSubviews()中,呼叫超级 第一

我是这么做的:

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


}

斯威夫特5号解决方案

您可以在 XCode11上运行 Swift 5尝试此实现


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
}
    

    

}