【问题标题】:Loading overlay causes issues when task is too short当任务太短时,加载覆盖会导致问题
【发布时间】:2018-07-12 12:41:10
【问题描述】:

我正在根据这个主题使用加载模式:

Loading an "overlay" when running long tasks in iOS

我在几个 ViewController 中使用相同的代码,所以我创建了一个扩展:

extension UIViewController {
    func showLoading() {
        let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        alert.view.addSubview(loadingIndicator)

        present(alert, animated: false, completion: nil)
    }

    func hideLoading() {
        if ( presentedViewController != nil && !presentedViewController!.isBeingPresented ) {
            dismiss(animated: false, completion: nil)
        }
    }
}

我通常使用这样的代码:

self.showLoading()
callNetwork() { response in
    DispatchQueue.main.async {
       self.hideLoading()
       ....
    }
}

如果网络调用需要 0.5 秒或更长时间,则一切正常。问题是网络是否太快。然后我会得到一个类似的错误:

Warning: Attempt to dismiss from view controller <UINavigationController: 0x7ff581830a00> while a presentation or dismiss is in progress!

而且模态不会被关闭。

我能想到的最好的解决方案是这样的(超类而不是扩展,因为扩展不能有变量):

class LoadingViewController: UIViewController {
    var shouldDismissImmediately = false

    func showLoading() {
        shouldDismissImmediately = false
        let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        alert.view.addSubview(loadingIndicator)

        present(alert, animated: false) {
             if (self.shouldDismissImmediately) {
                 self.dismiss(animated: false, completion: nil)
             }
        }
    }

    func hideLoading() {
        if ( presentedViewController != nil && !presentedViewController!.isBeingPresented ) {
            dismiss(animated: false, completion: nil)
        } else {
           shouldDismissImmediately = true
        }
    }
}

谁能想到更好的解决方案?就是这个感觉不太对。也许我在做一些根本错误的事情。就像 - 在等待网络响应时,我什至应该呈现这样的对话框吗?有没有更好的方法让用户等待?我需要用户意识到正在发生某些事情,同时我需要他不能按 UI 中的任何按钮。

【问题讨论】:

    标签: ios iphone swift


    【解决方案1】:
    extension UIViewController {
        func showLoading(finished: @escaping () -> Void) {
            let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
    
            let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
            loadingIndicator.hidesWhenStopped = true
            loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
            loadingIndicator.startAnimating();
    
            alert.view.addSubview(loadingIndicator)
    
            present(alert, animated: false, completion: finished)
        }
    
        func hideLoading(finished: @escaping () -> Void) {
            if ( presentedViewController != nil && !presentedViewController!.isBeingPresented ) {
                dismiss(animated: false, completion: finished)
            }
        }
    }
    
    self.showLoading(finished: {
        callNetwork() {
            DispatchQueue.main.async {
                self.hideLoading(finished: {
                    // done
                 })
             }
         }
    })
    

    【讨论】:

      猜你喜欢
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2015-03-13
      • 2013-05-22
      • 1970-01-01
      • 2016-12-16
      相关资源
      最近更新 更多