Ios 长时间运行异步任务-如何在用户可能已导航到的任何视图控制器中接收回调
在我的iOS Swift应用程序中,我启动了一个长时间运行的异步任务(由应用程序生命周期内存在的一个单例控制),将一些数据上传到服务器。通常,此任务最多可能需要10秒钟,在此期间,他们很可能已经离开启动异步任务的视图控制器。当任务完成后,我想向用户显示一条消息,无论用户在应用程序中的哪个位置。 是否有一种简单的方法可以显示对话框/消息/任何内容,而无需在每次创建新视图控制器时注册新委托Ios 长时间运行异步任务-如何在用户可能已导航到的任何视图控制器中接收回调,ios,swift,asynchronous,viewcontroller,Ios,Swift,Asynchronous,Viewcontroller,在我的iOS Swift应用程序中,我启动了一个长时间运行的异步任务(由应用程序生命周期内存在的一个单例控制),将一些数据上传到服务器。通常,此任务最多可能需要10秒钟,在此期间,他们很可能已经离开启动异步任务的视图控制器。当任务完成后,我想向用户显示一条消息,无论用户在应用程序中的哪个位置。 是否有一种简单的方法可以显示对话框/消息/任何内容,而无需在每次创建新视图控制器时注册新委托 在我的android应用程序中,它也可以做同样的事情,我可以随时显示一个toast(即对话框),无论当时显示的
在我的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
。在这种情况下,问题归结为获取当前显示的视图控制器,以便您可以显示该警报控制器。这里有一种方法:而且,您需要在主线程上运行它,而不是在异步线程上运行它。这是一个非常有用的答案!感谢您提供的所有示例。我还没有机会尝试,但在接下来的几天里会成功的。