Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 长时间运行异步任务-如何在用户可能已导航到的任何视图控制器中接收回调_Ios_Swift_Asynchronous_Viewcontroller - Fatal编程技术网

Ios 长时间运行异步任务-如何在用户可能已导航到的任何视图控制器中接收回调

Ios 长时间运行异步任务-如何在用户可能已导航到的任何视图控制器中接收回调,ios,swift,asynchronous,viewcontroller,Ios,Swift,Asynchronous,Viewcontroller,在我的iOS Swift应用程序中,我启动了一个长时间运行的异步任务(由应用程序生命周期内存在的一个单例控制),将一些数据上传到服务器。通常,此任务最多可能需要10秒钟,在此期间,他们很可能已经离开启动异步任务的视图控制器。当任务完成后,我想向用户显示一条消息,无论用户在应用程序中的哪个位置。 是否有一种简单的方法可以显示对话框/消息/任何内容,而无需在每次创建新视图控制器时注册新委托 在我的android应用程序中,它也可以做同样的事情,我可以随时显示一个toast(即对话框),无论当时显示的

在我的iOS Swift应用程序中,我启动了一个长时间运行的异步任务(由应用程序生命周期内存在的一个单例控制),将一些数据上传到服务器。通常,此任务最多可能需要10秒钟,在此期间,他们很可能已经离开启动异步任务的视图控制器。当任务完成后,我想向用户显示一条消息,无论用户在应用程序中的哪个位置。 是否有一种简单的方法可以显示对话框/消息/任何内容,而无需在每次创建新视图控制器时注册新委托


在我的android应用程序中,它也可以做同样的事情,我可以随时显示一个toast(即对话框),无论当时显示的是哪个片段(即View Controller)——而不必在片段中实现特殊行为,当祝酒词显示在片段的父对象上时。

我认为您正在寻找的魔法是

func getTopViewController(_ viewController: UIViewController? = UIApplication.shared.delegate?.window??.rootViewController) -> UIViewController? {
    if let tabBarViewController = viewController as? UITabBarController {
        return getTopViewController(tabBarViewController.selectedViewController)
    } else if let navigationController = viewController as? UINavigationController {
        return getTopViewController(navigationController.visibleViewController)
    } else if let presentedViewController = viewController?.presentedViewController {
        return getTopViewController(presentedViewController)
    } else {
        return viewController
    }
}
我讨厌使用它,因为它不符合苹果的最佳实践,但在紧要关头,它将适用于更简单的故事板。您可以使用此视图控制器视图向添加消息

if let viewController = getTopViewController() {
    let toastLabel = UILabel(frame: frame)
    // set up labels background color and other properties...
    toastLabel.text = "your message" 
    // add the subview to the rootViewController
    viewController.view.addSubview(toastLabel)
    // easy animation
    UIView.animate(withDuration: 0.4, delay: duration, options: .curveEaseOut, animations: {
        toastLabel.alpha = 0.0
    }, completion: {(isCompleted) in
        toastLabel.removeFromSuperview()
    })
} else {
    print("Unable to get top view controller.")
}
确保仅在主调度队列中使用此选项

DispatchQueue.main.async {
    // ...
}
下面是一些使这个模块更加模块化和面向对象的技术

一种技巧是使用

用法:

Toast.makeToast(message: "This is a test", duration: 4.0) { (isCompleted) in
    print("completed: \(isCompleted)")
}
// or
Toast.makeToast(message: "This is a test", duration: 4.0)
// or just
Toast.makeToast(message: "This is a test")
UIApplication.shared.makeToast(message: "This is another test", duration: 4.0) { (isCompleted) in
    print("completed: \(isCompleted)")
}
您可以使用以下静态变量设置边框、背景色、textColor、textAlignment、字体、alpha和cornerRadius:

Toast.frame = CGRect(
    x: UIScreen.main.bounds.size.width/2 - (UIScreen.main.bounds.size.width/2 - 16),
    y: UIScreen.main.bounds.size.height - 100,
    width: UIScreen.main.bounds.size.width - 32,
    height: 35
)
Toast.backgroundColor = UIColor.blue
Toast.textColor = UIColor.green
Toast.textAlignment = .left
Toast.font = UIFont.systemFont(ofSize: 14.0)
Toast.alpha = 0.8
Toast.cornerRadius = 8.0
另一个技巧是

用法:

Toast.makeToast(message: "This is a test", duration: 4.0) { (isCompleted) in
    print("completed: \(isCompleted)")
}
// or
Toast.makeToast(message: "This is a test", duration: 4.0)
// or just
Toast.makeToast(message: "This is a test")
UIApplication.shared.makeToast(message: "This is another test", duration: 4.0) { (isCompleted) in
    print("completed: \(isCompleted)")
}
通过将帧、背景颜色、文本颜色、文本对齐、字体、alpha和cornerRadius及其标记传递到函数中,可以设置帧、背景颜色、文本颜色、文本对齐、字体、alpha和cornerRadius:

UIApplication.shared.makeToast(
    message: "This is another test",
    duration: 4.0,
    frame: CGRect(
        x: UIScreen.main.bounds.size.width/2 - (UIScreen.main.bounds.size.width/2 - 16),
        y: UIScreen.main.bounds.size.height - 100,
        width: UIScreen.main.bounds.size.width - 32,
        height: 35
    ),
    backgroundColor: UIColor.blue.withAlphaComponent(0.6),
    textColor: UIColor.red,
    textAlignment: NSTextAlignment.left,
    font: UIFont.systemFont(ofSize: 16.0),
    alpha: 1.0,
    cornerRadius: 10
) { (isCompleted) in
    print("completed: \(isCompleted)")
}


您可以使用
NSNotification
NSNotificationCenter
在回调完成时发送通知,并在您可能拥有的任何ViewController中注册通知。

我假设您使用的是
UIAlertController
。在这种情况下,问题归结为获取当前显示的视图控制器,以便您可以显示该警报控制器。这里有一种方法:而且,您需要在主线程上运行它,而不是在异步线程上运行它。这是一个非常有用的答案!感谢您提供的所有示例。我还没有机会尝试,但在接下来的几天里会成功的。