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




