5

I am looking to create a custom subclass of UIAlertController. If I understand correctly, I need to call the super.init(title... somewhere during the subclasses initialization.

But I keep running into problems with designated initializers. I have read the documentation and cannot figure out how to get it to work. Here's my code (note the comments in the code):

class AccountInfoActionSheet: UIAlertController {

    required init?(coder aDecoder: NSCoder) { //xcode says I need this
        super.init(coder: aDecoder) //it also says I need to call a designated initializers so here it is
        super.init(title: "Info", message: "Heres the Info", preferredStyle: .actionSheet) //but now I can't call this initializer
        fatalError("init(coder:) has not been implemented")
    }
}

EDIT: Since UIAlertController cannot be subclassed I simply created a function that returns the correctly configured UIAlertController inside the ViewController where it is needed.

Marmelador
  • 947
  • 7
  • 27

4 Answers4

10

You should not subclass UIAlertController.

Check this link:

https://developer.apple.com/documentation/uikit/uialertcontroller#//apple_ref/doc/uid/TP40014538-CH1-SW2

you can add methods using extensions but should not subclass it.

Amit
  • 4,837
  • 5
  • 31
  • 46
  • 2
    You can, but you shouldn't. – Abizern Aug 26 '17 at 12:26
  • @Abizern: is it ? Can you please tell me how or where can I read the documentation related to it. – Amit Aug 26 '17 at 12:29
  • 2
    Also - if you look at the header you can see that UIAlertController is an `open` class, not `final` so you can, technically subclass it, but the documentation clearly states that you shouldn't. Nor should you mess about with it's view hierarchy. – Abizern Aug 26 '17 at 12:35
3

If you want an easier way of creating common alert controllers, what you can do instead of creating a subclass is to create an extension of UIAlertController that has a factory method to return the kind of configured Alert controller that you want. For example:

extension UIAlertController {

    static func accountInfo() -> UIAlertController {
        // If you want to add Alert Actions you can add them to the controller before returning them.
        return UIAlertController(title: "Info", message: "Here's the Info", preferredStyle: .actionSheet)
    }
}

And now you can create the controller simply with:

let ac = UIAlertController.accountInfo()
Abizern
  • 146,289
  • 39
  • 203
  • 257
3

As was stated in other answers you are not supposed to subclass UIAlertController. As an option you could create an extension with a factory method:

extension UIAlertController {
    static func accountInfoActionSheet() -> UIAlertController {
        return UIAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
    }
}

However, other answers are not particularly truthful saying that you cannot subclass UIAlertController. You are not supposed to, but you very much can if you want to.

UIAlertController is a subclass of UIViewController, therefore they have the same designated initializer which is init(nibName: String?, bundle: Bundle?).

You are not supposed to call it in init?(coder aDecoder: NSCoder) though because it is a designated initializer itself. It's being called when, for example, the controller is being initialized from a storyboard.

Here's the example how to achieve what you want (even though Apple does not approve that):

class AccountInfoActionSheet: UIAlertController {

    // preferredStyle is a read-only property, so you have to override it
    override var preferredStyle: UIAlertControllerStyle {
        return .actionSheet
    }

    init() {
        super.init(nibName: nil, bundle: nil)
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialize()
    }

    // all of the configuration code that init methods might share
    // separated into a method for the sake of convenience
    private func initialize() {
        title = "Info"
        message = "Heres the Info"
        // any other setup needed
    }
}
Lësha Turkowski
  • 1,361
  • 1
  • 10
  • 21
1

As limon's answer to another question says, you are not supposed to subclass UIAlertController.

Per Apple's documentation:

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Arjun Yadav
  • 1,369
  • 1
  • 10
  • 23