【问题标题】:Swift - Add an loading alert before open next viewSwift - 在打开下一个视图之前添加加载警报
【发布时间】:2017-08-20 01:34:48
【问题描述】:

我有一个需要时间加载的视图控制器,因此,当我单击按钮或链接转到该视图时,我想显示一条警报消息让用户等待,因为该视图正在加载。

我该怎么做?我无法从其他视图关闭警报。

这是我的代码:

类 ViewControllerDetelleCliente:

@IBAction func verCrearPedido(_ sender: Any) {

    let alert = UIAlertController(title: nil, message: "Cargando...", preferredStyle: .alert)  
    alert.view.tintColor = UIColor.black
    let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) as UIActivityIndicatorView
    loadingIndicator.hidesWhenStopped = true
    loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
    loadingIndicator.startAnimating();

    alert.view.addSubview(loadingIndicator)
    present(alert, animated: true, completion: nil)

    let next:ViewControllerPedidoArticulos = storyboard?.instantiateViewController(withIdentifier: "PedidoArticulos") as! ViewControllerPedidoArticulos
    next.nuevoPedido = true
    self.navigationController?.pushViewController(next, animated: true)
}

类 ViewControllerPedidoArticulos:

func viewDidLoad() {
    super.viewDidLoad()        
    self.dismiss(animated: true, completion: nil)
}

我必须在哪里或如何放置.dismiss 函数?

【问题讨论】:

  • 您可以将 MBProgressHUD 与文本一起使用
  • 你最好在中显示一个活动视图或其他东西。设置视图控制器并在加载完成后将其隐藏。确保异步加载数据,以便视图控制器快速显示。
  • 在离开视图之前调用 viewWillDisappear 中的方法。
  • @bey23 我所说的同样是您需要首先移动到该控制器并在发出请求之前显示指示器,并在收到响应时简单地关闭它,如果您想在控制器内不显示任何内容,然后您可以隐藏您的表格视图并在您关闭控制器时显示。
  • @NiravD 是的,我现在就去做。

标签: ios swift view load alert


【解决方案1】:

首先,谢谢大家的回答。关键是以其他方式思考,您不应该在第一个视图中显示警报并在第二个视图中关闭它。你应该:

  1. 转到第二个视图
  2. 打开警报加载(它不起作用,我使用UIActivityIndicatorView 代替。将其添加到情节提要并创建变量)并开始加载所有数据。在我的情况下,我必须使用DispatchQueue.main.async来填充tableView,最后使用.reloadData()
  3. 加载时,关闭警报加载。

特别感谢 @NiravD 的这个想法。

我的代码:

@IBOutlet var cargando: UIActivityIndicatorView!

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.tableView.reloadData()
        cargando.stopAnimating()
        cargando.isHidden = true
}

override func viewDidLoad() {
        super.viewDidLoad()
        cargando.startAnimating()

        DispatchQueue.main.async {
            ... // load data 
        }
}

【讨论】:

    【解决方案2】:

    有几种方法可以做到这一点,但我正在编写使用闭包的最简单方法。

    第 1 步:在 'ViewControllerPedidoArticulos' 类中关闭

     let stopActivityBlock : (()->())?
    

    第二步:设置回调代码

    next.stopActivityBlock = { () in
    self.dismiss(animated: true, completion: nil)
    }
    

    第 3 步:

    从“ViewControllerPedidoArticulos”类的 viewDidLoad 方法调用它。

    class ViewControllerPedidoArticulos:
    
    func viewDidLoad() {
        super.viewDidLoad()        
        if stopActivityBlock != nil{
        stopActivityBlock()
    }
    }
    

    【讨论】:

    • 我正在尝试,但next.stopActivityBlock = { in self.dismiss(animated: true, completion: nil) } 给我一个错误:预期表达式
    • 对不起,闭包定义中有一个小语法错误(步骤:2)请检查编辑的答案。
    【解决方案3】:

    如果您想在ViewControllerPedidoArticulos 中显示ActivityIndicator,则需要将ActivityIndicator 放入该控制器中。显示 AlertController 和您的指示器,然后当您收到响应关闭控制器时发出任何异步请求。

    所以首先从您的按钮操作中删除ActivityIndicator 代码。

    @IBAction func verCrearPedido(_ sender: Any) {
    
        let next = storyboard?.instantiateViewController(withIdentifier: "PedidoArticulos") as! ViewControllerPedidoArticulos
        next.nuevoPedido = true
        self.navigationController?.pushViewController(next, animated: true)
    }
    

    ViewControllerPedidoArticulos 控制器中添加该代码,然后再发出任何异步请求,或者如果您在viewDidLoad 中发出请求,则可以将其添加到viewDidLoad 中。

    override func viewDidLoad() {
        super.viewDidLoad()
        //Show the indicator with alertController
        let alert = UIAlertController(title: nil, message: "Cargando...", preferredStyle: .alert)
        alert.view.tintColor = UIColor.black
        let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) as UIActivityIndicatorView
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();
    
        alert.view.addSubview(loadingIndicator)
        present(alert, animated: true, completion: nil)        
    }
    

    现在只需调用 dismiss 即可获得异步请求的响应。

    self.dismiss(animated: true)
    

    【讨论】:

      【解决方案4】:

      我认为你应该像这样将UIAlertController 对象传递给下一个视图控制器:

        let next:ViewControllerPedidoArticulos = storyboard?.instantiateViewController(withIdentifier: "PedidoArticulos") as! ViewControllerPedidoArticulos
          next.nuevoPedido = true
          next.objAlert = alert
          self.navigationController?.pushViewController(next, animated: true)
      

      然后在您的下一个视图控制器的 viewDidLoad 中关闭该警报,例如:

      func viewDidLoad(_ animated: Bool) {
          super.viewDidAppear(animated)  
      
         if let alert = objAlert as! UIAlertController{
           alert.dismiss(animated: true, completion: nil)
         }
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用我通常在从 API 加载一些数据时使用的第三方 pod 库“SVProgressHUD”,以便向用户执行加载视图。

        只需在你的 podfile 中安装 pod 并使用

        导入你的类
        import SVProgressHUD
        

        之后,只需使用以下代码在您的应用在后台执行某些工作时使用加载指示器。

        //Loading progress ui until the data is retrieved from the server
            SVProgressHUD.show(withStatus: "Loading...")
        
        //After completing the retrieval of data from server
         SVProgressHUD.dismiss()
        

        它非常简单,看起来很棒。唯一的先决条件是你应该知道如何安装 pods/cocoapods

        我希望它有所帮助。干杯。

        【讨论】:

        • 不使用库就没有别的办法了吗?
        • 老实说,我没有尝试任何其他方法来实现这一点,因为我发现这是最简单的。我相信也必须有其他方法。我希望您在 cmets 中得到所需的答案。 :]
        【解决方案6】:

        您必须将警报视图控制器交给第二个视图控制器,然后在那里将其关闭。比如:

        @IBAction func verCrearPedido(_ sender: Any) {
            // ...
            next.alertVC = alert
            // push
        }
        

        类 ViewControllerPedidoArticulos:

        var alertVC:UIAlertController?
        
        // viewDidLoad or maybe better:
        func viewDidLoad(_ animated: Bool) {
            super.viewDidAppear(animated)        
            self.alertVC?.dismiss(animated: true, completion: nil)
        }
        

        【讨论】:

        • 我尝试了您的解决方案,我认为这是个好主意,但它不起作用:(
        • 也许viewDidLoad 不是关闭它的正确位置。您可能需要“在计算完成后”关闭它(在主线程上;使用 DispatchQueue.main.async
        猜你喜欢
        • 1970-01-01
        • 2019-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-05
        • 2011-04-24
        相关资源
        最近更新 更多