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

Dou*_*ith 113 cocoa-touch instantiation uiview ios swift

假设我想要init一个UIView带a String和a的子类Int.

如果我只是子类化,我将如何在Swift中执行此操作UIView?如果我只是创建一个自定义init()函数,但参数是一个字符串和一个Int,它告诉我"在从初始化程序返回之前不调用"super.init()".

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

Wol*_*lly 180

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 然后一定要把它们变成`var`.但Swift中的默认最佳实践是声明变量`let`,除非有理由将它们声明为`var`.在上面的代码示例中没有这样的理由,因此`let`. (4认同)
  • 有趣的是多年前编译的.现在它在init(编码器:)下抱怨"属性self.s未在super.init调用时初始化" (3认同)
  • 此代码无法编译。您需要实现所需的初始化程序`init(coder:)`。 (2认同)

MH1*_*175 23

我为指定和必需创建一个公共init.为方便起见,我委托给init(frame:)零帧.

拥有零帧不是问题,因为通常视图位于ViewController的视图中; 当您的超级视图调用layoutSubviews()或时,您的自定义视图将获得布局其子视图的良好,安全的机会updateConstraints().系统在整个视图层次结构中以递归方式调用这两个函数.你可以使用updateContstraints()layoutSubviews().updateContstraints()先叫,然后layoutSubviews().在updateConstraints()请确保调用超级最后.在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
      }

}
Run Code Online (Sandbox Code Playgroud)

  • 它不应该工作:在 super.init 初始化 self 之前在方法调用 'commonInit' 中使用 'self' (2认同)

J-D*_*zle 17

以下是我在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"); }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这将使用View的整个显示 (2认同)

小智 12

Swift 5 解决方案

您可以尝试使用此实现在 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
    }
    
    
}


Run Code Online (Sandbox Code Playgroud)

  • 您还可以添加 `private init() { fatalError() }` 以确保必须使用您的自定义 init (2认同)

J-D*_*zle 11

以下是我在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"); }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好地使用了fatalError()调用.我不得不使用选项来沉默来自甚至没有被使用的初始化器的警告.这把它关上了!谢谢. (3认同)