13

Trying to subclass UIButton but the error Must call a designated initializer of the superclass 'UIButton' occurs.

Researching several SO posts like this, this, this, or several others did not help as those solutions didn't work.

How can we subclass UIButton in Swift and define a custom init function?

import UIKit

class KeyboardButton : UIButton {
    var letter = ""
    var viewController:CustomViewController?

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

    init(letter: String, viewController: CustomViewController) {
        super.init()
        ...
    }
}
Community
  • 1
  • 1
Crashalot
  • 33,605
  • 61
  • 269
  • 439
  • 1
    As the error says you can't call `super.init()` as that isn't a designated initialiser. You will need to call `super.init(frame:frame)`, which means you will need to supply a frame to your initialiser. Having said that, this looks pretty awful. You should probably implement a delegate pattern rather than supplying a view controller to the initialiser – Paulw11 Sep 02 '15 at 01:23
  • Good point @Paulw11 thanks for the suggestion. New to Swift so the suggestion is most appreciated. – Crashalot Sep 02 '15 at 03:00

1 Answers1

23

You have to call the superclass' designated initializer:

Swift 3 & 4:

init(letter: String, viewController: CustomViewController) {
    super.init(frame: .zero)
}

Swift 1 & 2:

init(letter: String, viewController: CustomViewController) {
    super.init(frame: CGRectZero)
}

As Paulw11 says in the comments, a view generally shouldn't have a reference to its controller, except as a weak reference using the delegate pattern, which would promote reusability.

Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Thanks! New to Swift, so the delegate pattern is a great suggestion. Seems hackish to use `CGRectZero` as the initial frame only to change it later. There is no way to use the initializer with no parameters? Thanks for your help! – Crashalot Sep 02 '15 at 03:06
  • 4
    The designated initializer has one non-optional parameter, so there is no way to call it without parameters. If it makes you feel better, `init()` is just a convenience initializer that calls `init(frame: CGRectZero)` anyway. – Aaron Brager Sep 02 '15 at 03:08
  • But how do you set the button type in the subclass? – Tod Cunningham Apr 08 '16 at 21:54
  • @TodCunningham You can't do it in exactly the same way due to Swift's strict type safety. See http://stackoverflow.com/q/24014122/1445366 for some other approaches. – Aaron Brager Apr 09 '16 at 05:18