ios – Is an empty subclass of UIAlertController safe for use with `appearance(whenContainedInInstancesOf:)`


Somebody here on SO wanted to alter the behavior of UIAlertAction buttons in a specific UIAlertController, but not others. (They wanted multi-line button labels one for one alert.)

If you read the docs for UIAlertController it says that

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

As an experiment, I decided to try creating a dummy, empty subclass of UIAlertController, purely so that I had a class name to give to the UIAppearance method appearance(whenContainedInInstancesOf:)

The definition of the dummy subclass is just this:

class FooController: UIAlertController {
}

That then lets me use the statement

        UILabel.appearance(whenContainedInInstancesOf: [FooController.self]).numberOfLines = 2

and override the appearance of UILabels specifically in instances ofFooController

It works, seemingly flawlessly.

You can download the sample project from Github here.

When you create a vanilla UIAlertController, its UIAlertAction buttons have single-line labels as normal. When you create a FooController, its UIAlertAction buttons have multi-line labels.

While it seems to work perfectly, I am leery of going against an explicit statement in Apple’s docs not to subclass UIAlertController.

What are the risks of ignoring that admonition and using an empty subclass?

Here is the code from my sample project for reference:

import UIKit

class FooController: UIAlertController {
}

class ViewController: UIViewController {
    
    let buttonLabels = [
    """
    Button1
    line2
    """,
    """
    Button2
    line2
    """,
    """
    Button3
    line2
    """
    ]

    @IBAction func handleAlertButton(_ sender: Any) {
        presentAlert(type: UIAlertController.self)
    }
    
    @IBAction func handleFooButton(_ sender: Any) {
        presentAlert(type: FooController.self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        UILabel.appearance(whenContainedInInstancesOf: [FooController.self]).numberOfLines = 2
    }
    
    func presentAlert(type: UIAlertController.Type) {
        let sheet = type.init(title: type.description(), message: nil, preferredStyle: .actionSheet)
        for buttonTitle in buttonLabels {
            let item = UIAlertAction(title: buttonTitle, style: .default) { (action) in
                print("Button \(buttonTitle) tapped")
            }
            sheet.addAction(item)
        }
        present(sheet, animated: true, completion: nil)
    }
}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img