这里有人想要改变特定UIAlertControllerUIAlertAction个按钮的行为,而不是其他人.(他们希望一个alert 有多行按钮标签,但所有其他alert 的行为正常.)

如果你读UIAlertController美元的文件,上面写着

UIAlertController类旨在按原样使用,不支持子类化.此类的视图层次 struct 是私有的,不得修改.

作为实验,我决定try 创建一个UIAlertController的虚拟空子类,这样我就有一个类名可以提供给UI外观方法appearance(whenContainedInInstancesOf:)

虚拟子类的定义如下所示:

class FooController: UIAlertController {
}

这样我就可以使用以下语句

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

并特别在FooController的实例中覆盖UILabel的外观

它很管用,看起来无懈可击.

您可以从Github here下载样例项目.

当你创建一款香草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)
    }
}

推荐答案

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

  1. 苹果可能会拒绝这款apply.
  2. 在future 的iOS更新中,UIAlertController可能无法正常运行.
  3. 该子类的特定原因(使用UILabel.appearance)可能在将来的iOS更新中无法正常运行.

这些都是可能的风险.

虽然苹果总是拥有最终决定权,但苹果不太可能仅仅因为你以这种方式将UIAlertController细分为子类别而拒绝一款apply.我个人已经细分了几个UIKit类,苹果说这些类不应该细分.我在一款应用程序中做到了这一点,这款应用程序已经在应用程序store 中使用了很多年,并进行了多次更新.您没有使用任何私有API.苹果并没有说你不能低于UIAlertController.它说,这个类不打算被子类化.

这导致了第二个风险.苹果声明,UIAlertController不打算被子类化,也不支持子类化.这意味着它不提供任何要被覆盖或修改的API.但这并不意味着您不能子类化它来添加帮助器方法.或者简单地给这个类一个新的名字,这样你就可以做一些像你的UILabel.appearance一样的事情.您的子类是良性的,不会试图修改功能或挖掘私有子视图 struct .它是一个"安全"的子类,不会 destruct 任何现有的功能.

最后,风险3.虽然风险很小,但这可能是3的"最大"风险.苹果可能会在future 的iOS更新中对UIAlertController进行任意数量的更改,这可能会阻碍或打破在你的子类上使用UILabel.appearance的预期结果.在iOS的每个版本上测试代码都是谨慎的.最糟糕的情况很可能是,"黑客"将停止工作.

Ios相关问答推荐

在视图上执行手势会阻止相机操作

为什么EKEventStore().questFullAccessToEvents()可以与模拟器一起使用,而不能与真实设备一起使用?

如何根据SWIFT中的按钮点击更新文本值

Toast 不显示 Flutter

SwiftUI 中的描边图像边框

小部件链接有效,但不执行任何操作

将值传递给导航链接视图中的文本框

无法为 Flutter 项目构建 ipa [CocoaPods 找不到 pod "GoogleAppMeasurement" 的兼容版本:]

UIViewControllerRepresentable 在 Xcode 14 iOS 16 上崩溃

按钮在 SwiftUI 中没有采用给定的高度和宽度

有什么方法可以预填充核心数据?

Xcode - 错误 ITMS-90635 - Bundle 包中的 Mach-O 无效 - 提交到 App Store

未找到签名证书​​iOS Distribution

在 iOS 7 上更改标签栏色调 colored颜色

Xcode / iOS模拟器:手动触发重大位置更改

如何在 Objective-C 中组合两个数组?

无效的 iPhone 应用程序二进制文件

有什么方法可以加粗 NSString 的一部分?

在 UITableViewController 中使用 UISearchDisplayController 时断言失败

iOS13状态栏背景 colored颜色 与大文本模式下的导航栏不同