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.

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”.

  • UIView: opaque vs. alpha vs. opacity
  • iOS: Simultaneous scale and 3D rotation animation
  • CALayers didn't get resized on its UIView's bounds change. Why?
  • iPhone: How to set UIViewController frame?
  • When should I set layer.shouldRasterize to YES
  • Passing touch events to appropriate sibling UIViews
  • 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?

    4 Solutions Collect From Internet About “How do I write a custom init for a UIView subclass in Swift?”

    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 let variable declarations to var and optional. In this case, you would initialize them in awakeFromNib() or at some later time.

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

    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:

    • UIView Example Project (with SubView 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"); }
    }
    

    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. The superview calls layoutSubviews() or updateConstraints() which is called by the system recursively throughout the view hierarchy.

    If your custom view has subviews, you can set the subviews’ frames either in 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:

    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()
          }
    
          private func commonInit() {
               //custom initialization
          }
    
          override func updateConstraints() {
               //set subview constraints here
               super.updateConstraints()
          }
    
          override func layoutSubviews() {
               super.layoutSubviews()
               //manually set subview frames here
          }
    
    }