Swift:自定义 UIAlertController 视图



文档说子类化UIAlertController很糟糕

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

那么,推荐的警报方法是什么,它不仅显示标题、消息和一些按钮,还显示进度条、列表等其他内容?

在我的特殊情况下,我希望有两个不同的警报,一个显示进度条,另一个显示错误消息列表。

目前,我正在尝试手动添加进度视图并设置约束:

func getProgressAlert(onAbort: @escaping () -> ()) -> UIAlertController {
let alert = UIAlertController(title: "Test", message: "Test", preferredStyle: .alert)
let abort = UIAlertAction (title: "Abort", style: UIAlertActionStyle.cancel) { _ in
onAbort()
}
alert.addAction(abort)
let margin:CGFloat = 8.0
let rect = CGRect(x:margin, y:72.0, width: alert.view.frame.width - margin * 2.0 , height:2.0)
self.progressView = UIProgressView(frame: rect)
self.progressView!.setProgress(0.0, animated: false)
self.progressView!.tintColor = UIColor.blue
alert.view.addSubview(self.progressView!)
self.progressView!.translatesAutoresizingMaskIntoConstraints = false
self.progressView!.widthAnchor.constraint(equalTo: alert.view.widthAnchor, multiplier: 1.0).isActive = true
self.progressView!.heightAnchor.constraint(equalToConstant: 5.0).isActive = true
self.progressView!.topAnchor.constraint(equalTo: alert.view.topAnchor).isActive = true
self.progressView!.leftAnchor.constraint(equalTo: alert.view.leftAnchor).isActive = true       
return alert
}

我不认为这是应该这样做的方式,因为手动定义约束很容易在不同设备上出错。例如,当前代码仅在警报视图顶部显示进度条,但我希望它显示在消息和中止按钮之间。

此类的视图层次结构是私有的,不得修改。

这几乎是这个API的棺材上的钉子。如果您尝试破解它,您将在尝试跨不同的iOS版本支持它时给自己带来很多痛苦。

如果要在警报上具有自定义控件,则必须编写自定义UIViewController子类,并在添加新功能时尽可能模仿 API(如果不想这样做,GitHub 上将提供示例)。

一些例子:

  • https://github.com/Codeido/PMAlertController
  • https://github.com/Orderella/PopupDialog
  • https://github.com/vikmeup/SCLAlertView-Swift
  • https://github.com/sberrevoets/SDCAlertView

文档确实不鼓励子类化UIAlertController。但是,很容易找到人们绕过这一点并将子视图偷偷添加到警报视图的示例,但他们这样做的风险是次要的iOS版本更新破坏它。

苹果设置这种限制的一个重要原因是因为他们保留在幕后更改此类工作方式的权利。UIAlertController做了很多繁重的工作,它被许多应用程序使用,包括Apple提供的应用程序。

但它只做它做的事,不做它不做的事。我不认为UIAlertController不支持您描述的模态进度指示用例是偶然的。这些类型的 UI"包版"与良好的用户体验相冲突。

有没有另一种方法可以在不使用模态的情况下实现相同的目标?这可能涉及在工作完成之前禁用 UI 的其他方面,但仍允许用户导航。 这将产生更好的用户体验。

但是,如果这对您不起作用,并且您必须使用路障模式进度指示器,承认它产生的负面用户体验,那么构建自己的模式进度指示器会更加谨慎和可靠。UIAlertController 没什么特别的,它是一个 UIViewController 和其他任何控制器一样。它使用公开可用的 API 来控制其帧大小、如何覆盖其呈现视图以及如何在屏幕上和屏幕外进行动画处理。通过滚动自己,您将省去很多麻烦。