【问题标题】:Cant Dismiss UIAlertController From Separate Function无法从单独的函数中解除 UIAlertController
【发布时间】:2017-08-20 22:04:24
【问题描述】:

我有一个没有按钮的 UIAlertController(我将此警报用作一些数据加载消息时请稍候),我在我的视图控制器的 viewDidLoad 函数中显示。显示警报后,我运行一个从数据库中检索信息的函数,一旦完成,我想解除警报,以便用户可以继续,但是警报似乎在运行后没有解除:

self.dismiss(animated: true, completion: nil)

我还尝试将我的 uialertcontroller 作为参数传递给函数并运行以下行但没有运气:

alertController.dismiss(animated: false, completion: nil)

编辑:这是我的 viewDidLoad 函数以及应该解除警报的函数

override func viewDidLoad() {
    super.viewDidLoad()

    let alertController = UIAlertController(title: "Loading", message:
        "This might take a moment", preferredStyle: UIAlertControllerStyle.alert)

    self.present(alertController, animated: true, completion: nil)
    hideAlert(alert: alertController)
}

func hideAlert(alert: UIAlertController) {
let hideAlertController = { () -> Void in 
alertController.dismiss(animated: false, completion: nil)
}
FIRDatabase.database().reference().child("info").observeSingleEvent(of: .value, with: { (dataSnapshot) in
        DispatchQueue.main.async {
            hideAlertController()
        }
    })
}

【问题讨论】:

    标签: ios swift3 uialertcontroller dismiss


    【解决方案1】:

    在你的 ViewController 中试试这个:

    var operationPerformed : Bool = false;
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning();
        // Dispose of any resources that can be recreated.
    }
    
    override func viewDidLoad() {
        super.viewDidLoad();
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated);
        if(!self.operationPerformed){
            let alertController = UIAlertController(title: "Loading", message:
                "This might take a moment", preferredStyle: UIAlertControllerStyle.alert);
            self.present(alertController, animated: true, completion: nil);
            self.performOperation(alertToBeClosedOnFinish: alertController);
        }
    }
    
    func performOperation(alertToBeClosedOnFinish: UIAlertController) {
        let hideAlertController = { () -> Void in
            alertToBeClosedOnFinish.dismiss(animated: false, completion: nil)
        }
        DispatchQueue.global().asyncAfter(deadline: .now() + 2, execute: {
            DispatchQueue.main.async {
                hideAlertController();
                self.operationPerformed = true;
            }
        });
    }
    

    这个想法是在它的所有者处于层次结构中时显示警报控制器,如果我理解你的话 - 你想调用它一次,所以你应该检查操作是否已经执行。

    但这种方法的缺点是当您可以将进度视图创建为 UIView 的子类并将其添加到超级视图或从超级视图中删除时,尝试使用警报控制器。此外,还有很多 pod 可以帮助您实现这一目标。

    最好的问候, 谢尔盖

    【讨论】:

      【解决方案2】:

      让我们在viewDidAppear(_:) 方法中显示警报。如果没有,你会得到一个错误who view is not in the window hierarchy!

      override func viewDidAppear(_ animated: Bool) {
          super.viewDidAppear(animated)
      
          let alertController = UIAlertController(title: "Loading", message:
              "This might take a moment", preferredStyle: UIAlertControllerStyle.alert)
      
          self.present(alertController, animated: true, completion: nil)
      }
      
      func hideAlert(alert: UIAlertController) {
      
          let hide = { () -> Void in
              alert.dismiss(animated: true, completion: nil)
          }
      
          let task = URLSession.shared.dataTask(with: URL(string: "https://www.google.com/")!) { (data, response, error) in
      
              print("error: \(error)")
      
              DispatchQueue.main.async {
                  hide()
              }
          }
          task.resume()
      }
      

      它正在工作!

      【讨论】:

      • 我曾试图在 viewDidAppear 中关闭警报,但它没有被解除(抱歉,如果我误解了您的建议)
      • 我假设从 url 加载数据并在完成后隐藏警报。你可以看到我的更新!
      • 我实际上是从 firebase 实时数据库中检索数据,该数据库确实在与主线程分开的线程上运行,但是调用 DispatchQueue.main.async 内部的闭包对我不起作用。
      • 我认为您应该发布更多代码,然后人们可以帮助您
      • 我刚刚编辑了我的原始帖子,现在在我对 firebase 数据库的调用中包含了闭包调用,希望能解决我的问题。
      【解决方案3】:

      从数据库中检索信息的函数是否运行在不同的线程上?如果是这样,您将无法从该线程更新 UI。 UI 更新只能发生在主线程上。

      当你用这个包装你的代码时会发生什么? :)

      DispatchQueue.main.async {
          alertController.dismiss(animated: false, completion: nil)
      }
      

      【讨论】:

      • 我刚刚更新了原始帖子,正如我在编辑中所说的那样,我忘了提到我尝试在一个单独的线程上运行的闭包内解除警报,但是在将解除调用包装进去之后它没有关闭的异步(我也尝试用异步包装对闭包的调用,结果相同)
      猜你喜欢
      • 2018-06-08
      • 2014-10-26
      • 2019-09-04
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 2016-05-09
      相关资源
      最近更新 更多