Search code examples
iosswiftuiviewinitializationoverriding

overriding the initializer of my custom UIView subclass


this might be a stupid question, and I might kick myself, when I read the solution, but I am currenly stumped.

I have a custom UIView subclass:

let viewA: UIView = {...}
let viewB: UIView = {...}
let viewC: UIView = {...}
var subviews: [UIView]

class MyView: UIView {

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    init() {
      subviews = [viewA, viewB, viewC]
      super.init(frame: .zero)
      abc123(true)
    }

    func abc123(_ cols: Bool) { ... }
    ...
}

Now I want to make a slightly modified version of myView, but want to keep most of the logic. So a little later in the file I add:

class myAltView: MyView {

  required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }

  override init() {
    subviews = [viewA, viewC]
    super.init(frame: .zero)
    abc123(false)
  }

}

The error is obviously in the super.init(frame: .zero) of the subclass. It won't work, since the super doesn't have an implementation for that. I can't call super.super.init(frame: .zero), so how would I go about solving this?

So I then started to rework the "parent class" to contain an convenience init() and an init(subview: [UIView], cols: Bool), but again I was not able to successfully override the convenience init in the subclass it wanted me to call self.init which I was exactly trying to avoid defining in the subclass to avoid redundant code.

This should be easier, but I can't seem to think of the solution. Can anyone shed a little light onto this problem...

Thanks!


Solution

  • If you override init(frame:) in your superclass and simply call super's implementation from it, hence not changing its behaviour, the issue is resolved.

    class MyView: UIView {
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        init() {
            subviews = [viewA, viewB, viewC]
            super.init(frame: .zero)
            abc123(true)
        }
    
        func abc123(_ cols: Bool) {}
    
    }