[英]How do I write a custom init for a UIView subclass in Swift?
Say I want to init
a UIView
subclass with a String
and an Int
.假设我想用String
和Int
init
一个UIView
子类。
How would I do this in Swift if I'm just subclassing UIView
?如果我只是UIView
我将如何在 Swift 中做到这一点? 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".如果我只是创建一个自定义的init()
函数,但参数是一个 String 和一个 Int,它会告诉我“在从初始化程序返回之前没有调用 super.init()”。
And if I call super.init()
I'm told I must use a designated initializer.如果我调用super.init()
我被告知我必须使用指定的初始化程序。 What should I be using there?我应该在那里使用什么? The frame version?框架版? The coder version?编码器版本? Both?两个都? Why?为什么?
The init(frame:)
version is the default initializer. init(frame:)
版本是默认的初始值设定项。 You must call it only after initializing your instance variables.只有在初始化实例变量后才必须调用它。 If this view is being reconstituted from a Nib then your custom initializer will not be called, and instead the init?(coder:)
version will be called.如果此视图是从 Nib 重构的,则不会调用您的自定义初始化程序,而是调用init?(coder:)
版本。 Since Swift now requires an implementation of the required init?(coder:)
, I have updated the example below and changed the let
variable declarations to var
and optional.由于 Swift 现在需要实现所需的init?(coder:)
,我更新了下面的示例并将let
变量声明更改为var
和 optional。 In this case, you would initialize them in awakeFromNib()
or at some later time.在这种情况下,您将在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)
}
}
I create a common init for the designated and required.我为指定的和所需的创建了一个通用的 init。 For convenience inits I delegate to init(frame:)
with frame of zero.为了方便初始化,我委托给init(frame:)
框架为零。
Having zero frame is not a problem because typically the view is inside a ViewController's view;零帧不是问题,因为通常视图在 ViewController 的视图中; your custom view will get a good, safe chance to layout its subviews when its superview calls layoutSubviews()
or updateConstraints()
.当父视图调用layoutSubviews()
或updateConstraints()
时,您的自定义视图将获得一个很好的、安全的机会来布局其子视图。 These two functions are called by the system recursively throughout the view hierarchy.这两个函数由系统在整个视图层次结构中递归调用。 You can use either updateContstraints()
or layoutSubviews()
.您可以使用updateContstraints()
或layoutSubviews()
。 updateContstraints()
is called first, then layoutSubviews()
.首先调用updateContstraints()
,然后调用layoutSubviews()
。 In updateConstraints()
make sure to call super last .在updateConstraints()
确保调用 super last 。 In layoutSubviews()
, call super first .在layoutSubviews()
首先调用超。
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
}
}
Here is how I do it on iOS 9 in Swift -这是我在 Swift 中的 iOS 9 上的操作方法 -
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 -这是我如何在 Swift 中在 iOS 上执行子视图 -
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"); }
}
You can try out this implementation for running Swift 5 on XCode 11您可以尝试使用此实现在 XCode 11 上运行 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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.