是 UIAlertController 的空子类,可以安全地与“appearance(whenContainedInInstancesOf:)”一起使用

问题描述 投票:0回答:1

这里有人想要改变特定

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)
    }
}
ios uikit uialertcontroller subclassing
1个回答
1
投票

忽略该警告并使用空子类有哪些风险?

  1. Apple 可能会拒绝该应用程序。
  2. 在未来的 iOS 更新中,
    UIAlertController
    可能无法正常工作。
  3. 子类的具体原因(使用
    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 版本上测试代码是谨慎的做法。最坏的情况可能是“黑客”将停止工作。

© www.soinside.com 2019 - 2024. All rights reserved.