如何在视图控制器被关闭后显示警报
How to present an alert after view controller has been dismissed
我有一个应用,用户在后台上传文件通常需要几秒钟。当他们点击 "Done" 按钮并且同时关闭视图控制器时,上传开始。我希望发生的是下载完成后出现警报。我以为我只是将下面的代码添加到上传功能,但它不起作用。我怎样才能出现一个警告框来确认上传成功?
@IBAction func tapDone(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
if let image = newImage {
submit2Parse(image: image)
}
}
func submit2Parse (image: UIImage) {
if let pfImage = image2PFFile(image: image) {
// Insert PFFile into parse server
let submittedImage = PFObject(className: "Images")
submittedImage["imageFile"] = pfImage
submittedImage["type"] = "submittedFromUserHome"
submittedImage["bride"] = brideSwitch.isOn
submittedImage["groom"] = groomSwitch.isOn
submittedImage["user"] = userSwitch.isOn
submittedImage["picturePeriod"] = pickerSelected
submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? "" submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? ""
if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text }
submittedImage.saveInBackground { (success, error) in
if success {
let message = "Save in bg worked"
print(message)
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: {
(action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alert,animated: true, completion: nil)
} else {
print(error?.localizedDescription ?? "")
}
}
}
}
代码给出了这个构建错误:
Implicit use of 'self' in closure; use 'self.' to make capture semantics explicit
在你的tapDone
方法中,你需要使用completion
关闭你的控制器,像这样:
self.dismiss(animated: true) {
if let image = newImage {
self.submit2Parse(image: image)
}
}
这仅意味着 self.submit2Parse(image: image)
将仅在您关闭控制器后执行。此外,错误
Implicit use of 'self' in closure; use 'self.' to make capture
semantics explicit
only 意味着您需要使用 self.
在闭包中显式调用变量或方法。所以你的 submit2Parse...
现在应该是这样的:
self.submit2Parse(image: image)
.
如果我对你的问题的理解正确,你想在用户点击 tapDone
按钮时关闭你的 SecondViewController
。之后,一旦您的图片上传完成,您就会想要显示成功警报。
但是如果你 dismiss
它一旦点击按钮你将不会收到任何警报,因为你的 SecondViewController
不再在 window hierarchy
中,如果你尝试显示警报你将在控制台中收到如下错误:
Attempt to present on
whose view is not in the
window hierarchy!
要解决这个问题,您需要在您关闭第二个视图控制器后显示第一个视图控制器的警报,您可以使用 delegate
.
来实现
考虑以下示例:
首先在你的 FirstViewController
之外声明一个 protocol
:
protocol UplaodSuccessDelegate:class {
func uploadSuccess(message: String)
}
然后确认您的代理人相同 class:
class ViewController: FirstViewController, UplaodSuccessDelegate {
那么在present的时候需要通过delegate SecondViewController
:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
vc.delegate = self. //Pass delegate
self.present(vc, animated: true, completion: nil)
并将委托方法添加到相同的 class:
func uploadSuccess(message: String) {
let message = "Save in bg worked"
print(message)
let alert = UIAlertController(title: "title", message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: {
(action) in
}))
self.present(alert,animated: true, completion: nil)
}
现在在您的 SecondViewController
中您需要添加
weak var delegate: UplaodSuccessDelegate?
并在您的 tapDone
方法中将代码替换为:
self.dismiss(animated: true) {
if let image = newImage {
submit2Parse(image: image)
}
}
上传完成后,您需要调用委托方法(上传完成后),例如:
self.delegate?.uploadSuccess(message: "your message")
这将从 FirstViewController
.
调用您的委托方法
当你将下面的函数放到viewController中,在后台启动数据上传,然后在提交完成时触发的闭包中调用这个函数,它甚至能够成功创建一个警报认为最初的视图控制器被解雇了(如果是长时间上传,则被解雇了很长时间)。
// This is the function that performs my background upload
func submit2Parse (image: UIImage) {
if let pfImage = image2PFFile(image: image) {
// Insert PFFile into parse server
let submittedImage = PFObject(className: "Images")
submittedImage["imageFile"] = pfImage
submittedImage["imageCreateDt"] = newImageCreateDate
submittedImage["type"] = "submittedFromUserHome"
submittedImage["bride"] = brideSwitch.isOn
submittedImage["groom"] = groomSwitch.isOn
submittedImage["user"] = userSwitch.isOn
submittedImage["picturePeriod"] = pickerSelected
submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? ""
submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? ""
if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text }
// Get the image timestamp, every photo has one
// How do you get the thumbnail image too?
submittedImage.saveInBackground { (success, error) in
if success {
let message = "Save in bg worked"
print(message)
self.showAlertFromAppDelegates()
} else {
print(error?.localizedDescription ?? "")
}
}
}
}
// This is the function that creates the alert
func showAlertFromAppDelegates(){
var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
topWindow?.rootViewController = UIViewController()
topWindow?.windowLevel = UIWindow.Level.alert + 1
let alert: UIAlertController = UIAlertController(title: "Upload Complete", message: "Your image was successfully submitted!", preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (alertAction) in
topWindow?.isHidden = true
topWindow = nil
}))
topWindow?.makeKeyAndVisible()
topWindow?.rootViewController?.present(alert, animated: true, completion:nil)
}
我有一个应用,用户在后台上传文件通常需要几秒钟。当他们点击 "Done" 按钮并且同时关闭视图控制器时,上传开始。我希望发生的是下载完成后出现警报。我以为我只是将下面的代码添加到上传功能,但它不起作用。我怎样才能出现一个警告框来确认上传成功?
@IBAction func tapDone(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
if let image = newImage {
submit2Parse(image: image)
}
}
func submit2Parse (image: UIImage) {
if let pfImage = image2PFFile(image: image) {
// Insert PFFile into parse server
let submittedImage = PFObject(className: "Images")
submittedImage["imageFile"] = pfImage
submittedImage["type"] = "submittedFromUserHome"
submittedImage["bride"] = brideSwitch.isOn
submittedImage["groom"] = groomSwitch.isOn
submittedImage["user"] = userSwitch.isOn
submittedImage["picturePeriod"] = pickerSelected
submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? "" submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? ""
if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text }
submittedImage.saveInBackground { (success, error) in
if success {
let message = "Save in bg worked"
print(message)
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: {
(action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alert,animated: true, completion: nil)
} else {
print(error?.localizedDescription ?? "")
}
}
}
}
代码给出了这个构建错误:
Implicit use of 'self' in closure; use 'self.' to make capture semantics explicit
在你的tapDone
方法中,你需要使用completion
关闭你的控制器,像这样:
self.dismiss(animated: true) {
if let image = newImage {
self.submit2Parse(image: image)
}
}
这仅意味着 self.submit2Parse(image: image)
将仅在您关闭控制器后执行。此外,错误
Implicit use of 'self' in closure; use 'self.' to make capture semantics explicit
only 意味着您需要使用 self.
在闭包中显式调用变量或方法。所以你的 submit2Parse...
现在应该是这样的:
self.submit2Parse(image: image)
.
如果我对你的问题的理解正确,你想在用户点击 tapDone
按钮时关闭你的 SecondViewController
。之后,一旦您的图片上传完成,您就会想要显示成功警报。
但是如果你 dismiss
它一旦点击按钮你将不会收到任何警报,因为你的 SecondViewController
不再在 window hierarchy
中,如果你尝试显示警报你将在控制台中收到如下错误:
Attempt to present on whose view is not in the window hierarchy!
要解决这个问题,您需要在您关闭第二个视图控制器后显示第一个视图控制器的警报,您可以使用 delegate
.
考虑以下示例:
首先在你的 FirstViewController
之外声明一个 protocol
:
protocol UplaodSuccessDelegate:class {
func uploadSuccess(message: String)
}
然后确认您的代理人相同 class:
class ViewController: FirstViewController, UplaodSuccessDelegate {
那么在present的时候需要通过delegate SecondViewController
:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
vc.delegate = self. //Pass delegate
self.present(vc, animated: true, completion: nil)
并将委托方法添加到相同的 class:
func uploadSuccess(message: String) {
let message = "Save in bg worked"
print(message)
let alert = UIAlertController(title: "title", message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: {
(action) in
}))
self.present(alert,animated: true, completion: nil)
}
现在在您的 SecondViewController
中您需要添加
weak var delegate: UplaodSuccessDelegate?
并在您的 tapDone
方法中将代码替换为:
self.dismiss(animated: true) {
if let image = newImage {
submit2Parse(image: image)
}
}
上传完成后,您需要调用委托方法(上传完成后),例如:
self.delegate?.uploadSuccess(message: "your message")
这将从 FirstViewController
.
当你将下面的函数放到viewController中,在后台启动数据上传,然后在提交完成时触发的闭包中调用这个函数,它甚至能够成功创建一个警报认为最初的视图控制器被解雇了(如果是长时间上传,则被解雇了很长时间)。
// This is the function that performs my background upload
func submit2Parse (image: UIImage) {
if let pfImage = image2PFFile(image: image) {
// Insert PFFile into parse server
let submittedImage = PFObject(className: "Images")
submittedImage["imageFile"] = pfImage
submittedImage["imageCreateDt"] = newImageCreateDate
submittedImage["type"] = "submittedFromUserHome"
submittedImage["bride"] = brideSwitch.isOn
submittedImage["groom"] = groomSwitch.isOn
submittedImage["user"] = userSwitch.isOn
submittedImage["picturePeriod"] = pickerSelected
submittedImage["uploadedByUserId"] = PFUser.current()?.objectId ?? ""
submittedImage["uploadedByUserName"] = PFUser.current()?.username ?? ""
if !txtIsPlaceHolder { submittedImage["description"] = imageDescription.text }
// Get the image timestamp, every photo has one
// How do you get the thumbnail image too?
submittedImage.saveInBackground { (success, error) in
if success {
let message = "Save in bg worked"
print(message)
self.showAlertFromAppDelegates()
} else {
print(error?.localizedDescription ?? "")
}
}
}
}
// This is the function that creates the alert
func showAlertFromAppDelegates(){
var topWindow: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
topWindow?.rootViewController = UIViewController()
topWindow?.windowLevel = UIWindow.Level.alert + 1
let alert: UIAlertController = UIAlertController(title: "Upload Complete", message: "Your image was successfully submitted!", preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (alertAction) in
topWindow?.isHidden = true
topWindow = nil
}))
topWindow?.makeKeyAndVisible()
topWindow?.rootViewController?.present(alert, animated: true, completion:nil)
}