关于ios:Swift:自定义UIAlertController视图

Swift: Custom UIAlertController view

文档说子类化UIAlertController是不好的

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

那么,推荐一种不仅显示标题,消息和某些按钮,还显示其他东西(例如ProgressBars,List等)的警报的方法是什么?

在我的特殊情况下,我想使用两种不同的警报,一种显示一个ProgressBar,另一种显示一个错误消息列表。

目前,我正在尝试手动添加ProgressView并设置约束:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
}

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


The view hierarchy for this class is private and must not be modified.

这几乎是该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的其他方面,但仍允许用户导航。这将产生更好的用户体验。

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