Swift:自定义UIAlertController视图

时间:2018-04-06 16:31:54

标签: ios swift uialertcontroller uiprogressview

docs说UIAlertController的子类化不好

  

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

那么建议的方法是什么建议不仅显示标题,消息和一些按钮,还包括其他内容,如ProgressBars,Lists等?

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

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

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
}

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

2 个答案:

答案 0 :(得分:4)

  

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

这就是这个API的棺材中的钉子。如果您尝试破解它,那么在不同的iOS版本中尝试支持它会给您带来很多痛苦。

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

一些例子:

答案 1 :(得分:0)

文档确实不鼓励对UIAlertController进行子类化。然而,很容易找到人们绕过这个例子并将子视图隐藏到警报视图中的例子,但是他们这样做是为了让他们自己冒险破坏它的小版本。

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

但它只做它做的事情,而不做它没做的事情。我不认为UIAlertController不支持您描述的模态进度指示用例是一个意外。这些类型的UI“包版”与良好的用户体验相冲突。

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

但是,如果这对您不起作用,并且您必须使用包版模式进度指示器,承认其创建的负面用户体验,那么构建自己的用户操作会更加谨慎和可靠。 UIAlertController没什么特别的,它和其他任何一个UIViewController一样。它使用publicly available API来控制其帧大小,它如何覆盖其呈现视图,以及它如何在屏幕上和屏幕上设置动画。只需滚动自己就可以省去很多麻烦。