ios 如何在 Swift 中为 UIView 子类编写自定义初始化?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24339145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:02:15  来源:igfitidea点击:

How do I write a custom init for a UIView subclass in Swift?

iosswiftcocoa-touchuiviewinstantiation

提问by Doug Smith

Say I want to inita UIViewsubclass with a Stringand an Int.

假设我想要init一个UIView带有 aString和 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".

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

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?

如果我打电话,super.init()我被告知我必须使用指定的初始化程序。我应该在那里使用什么?框架版?编码器版本?两个都?为什么?

回答by Wolf McNally

The init(frame:)version is the default initializer. 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. Since Swift now requires an implementation of the required init?(coder:), I have updated the example below and changed the letvariable declarations to varand optional. In this case, you would initialize them in awakeFromNib()or at some later time.

init(frame:)版本是默认的初始值设定项。只有在初始化实例变量后才必须调用它。如果此视图是从 Nib 重构的,则不会调用您的自定义初始值设定项,而是init?(coder:)会调用版本。由于 Swift 现在需要实现 required 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)
    }
}

回答by MH175

I create a common init for the designated and required. For convenience inits I delegate to init(frame:)with frame of zero.

我为指定的和所需的创建了一个通用的 init。为了方便初始化,我委托给init(frame:)零帧。

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.

零帧不是问题,因为通常视图在 ViewController 的视图中;您的自定义视图将在其父视图调用layoutSubviews()updateConstraints(). 这两个函数由系统在整个视图层次结构中递归调用。您可以使用updateContstraints()layoutSubviews()updateContstraints()首先被调用,然后layoutSubviews()。在updateConstraints()确保调用 super last。在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
      }

}

回答by J-Dizzle

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:

这是一个带有示例的完整项目:

回答by J-Dizzle

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