Marmelador
Marmelador

Reputation: 1017

Initialising a subclass of UIAlertController

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.

Upvotes: 5

Views: 3869

Answers (4)

Amit
Amit

Reputation: 4886

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.

Upvotes: 11

Arjun Yadav
Arjun Yadav

Reputation: 1429

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.

Upvotes: 1

Lësha Turkowski
Lësha Turkowski

Reputation: 1391

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

Upvotes: 4

Abizern
Abizern

Reputation: 150605

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

Upvotes: 3

Related Questions