有人想改变UIAlertAction
特定按钮的行为UIAlertController
,但不想改变其他按钮的行为。(他们想要一个警报的多行按钮标签,但所有其他警报的正常行为。)(这是另一个问题的链接。)
如果您阅读文档,UIAlertController
它会说
UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。
作为一个实验,我决定尝试创建一个虚拟的空子类UIAlertController
,纯粹是为了给 UIAppearance 方法提供一个类名appearance(whenContainedInInstancesOf:)
虚拟子类的定义如下:
class FooController: UIAlertController {
}
然后我可以使用这个语句
UILabel.appearance(whenContainedInInstancesOf: [FooController.self]).numberOfLines = 2
UILabel
并特别在以下实例中覆盖 s 的出现FooController
它有效,看起来完美无缺。
您可以在此处从 Github 下载示例项目。
当您创建 vanilla 时UIAlertController
,它的UIAlertAction
按钮像平常一样具有单行标签。当您创建 时FooController
,它的UIAlertAction
按钮具有多行标签。
虽然它看起来工作得很好,但我对反对苹果文档中明确的声明而不是子类化持怀疑态度UIAlertController
。
忽略该警告并使用空子类有哪些风险?
这是我的示例项目中的代码供参考:
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)
}
}
忽略该警告并使用空子类有哪些风险?
UIAlertController
在 iOS 的未来更新中可能无法正常运行。UILabel.appearance
子类的具体原因(使用)可能在 iOS 的未来更新中无法正常运行。这些都是可能存在的风险。
虽然 Apple 始终拥有最终决定权,但 Apple 不太可能仅仅因为您
UIAlertController
以这种方式进行子类化而拒绝应用程序。我个人对几个 Apple 认为不应该进行子类化的 UIKit 类进行了子类化。我在一个应用程序中完成了此操作,该应用程序已在应用程序商店中存在多年并且已经进行了多次更新。您没有使用任何私有 API。Apple 并没有说你不能子类化UIAlertController
。它表示该类不打算被子类化。这会导致风险#2。Apple 声明
UIAlertController
不打算对其进行子类化,也不支持子类化。这意味着它不提供任何可覆盖或修改的 API。但这并不意味着您不能对其进行子类化以添加辅助方法等。或者只是给类一个新名称,以便您可以执行类似UILabel.appearance
. 您的子类是良性的,不会尝试修改功能或深入研究私有子视图结构。它是一个“安全”子类,不会破坏任何现有功能。最后,风险#3。虽然很小,但这可能是 3 中“最大”的风险。Apple 可能会在未来的 iOS 更新中进行任意数量的更改,这可能会阻碍或破坏在子类上
UIAlertController
使用的预期结果。UILabel.appearance
在每个 iOS 版本上测试代码是谨慎的做法。最坏的情况可能是“黑客”将停止工作。