这里有人想要改变特定
UIAlertAction
中 UIAlertController
按钮的行为,但不改变其他。 (他们想要一个警报的多行按钮标签,但所有其他警报的正常行为。)(这里是另一个问题的链接。)
如果您阅读了
UIAlertController
的文档,它会这样说
UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。
作为实验,我决定尝试创建一个虚拟的空子类
UIAlertController
,纯粹是为了给 UIAppearance 方法提供一个类名 appearance(whenContainedInInstancesOf:)
虚拟子类的定义就是这样:
class FooController: UIAlertController {
}
然后让我使用这个声明
UILabel.appearance(whenContainedInInstancesOf: [FooController.self]).numberOfLines = 2
并覆盖
UILabel
的外观,特别是在FooController
的实例中
它有效,看起来完美无缺。
您可以从 Github 此处下载示例项目。
当您创建普通
UIAlertController
时,其 UIAlertAction
按钮通常具有单行标签。当您创建 FooController
时,其 UIAlertAction
按钮具有多行标签。
虽然它似乎工作得很好,但我对违背苹果文档中的明确声明not到子类
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
可能无法正常工作。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 版本上测试代码是谨慎的做法。最坏的情况可能是“黑客”将停止工作。