无法从单独的函数中解雇 UIAlertController

Cant Dismiss UIAlertController From Separate Function

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

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()
        }
    })
}

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

用这个包装代码会发生什么? :)

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

让我们在 viewDidAppear(_:) 方法中显示警报。否则,您将得到一个错误 whose 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()
}

它正在运行!

在你的 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 的子类并添加或删除它时尝试使用警报控制器 to/from 超级视图。此外,还有很多 pods 可以帮助您实现这一目标。

此致, 谢尔盖