Reputation: 1980
I'm using a singleton class to validate a network response. Inside the function (validResponse()
) I'm calling in the singleton, I call another function which pops up an alert box, to let the user know there was an error.
The function inside my singleton class:
func validResponse(data: Data?, response: URLResponse?, error: Error?, viewController: UIViewController, context: String?) -> Bool {
...
DispatchQueue.main.async {
AlertHelper.showAlertWrapper(viewController: viewController, alertTitle: "Error", alertMessage: self.genericError)
}
}
The AlertHelper
code:
class AlertHelper {
static func showAlertWrapper(viewController: UIViewController, alertTitle: String, alertMessage: String) {
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert);
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil);
alertController.addAction(okAction);
viewController.present(alertController, animated: true, completion: nil);
}
}
Calling validResponse()
:
let result = self.networkHelper.validResponse(data: data, response: response, error: error, viewController: self, context: "Delete section")
In the above instance self
is not going to work, and is just temporarily there until I figure out what to do. I understand I could just pass the relevant UIViewController
in viewController
, like I did for showAlertWrapper
. However this is a bit messy.
Is there some way I can reference the currently present view controller in my singleton class, so that I dont have to pass it in validResponse()
?
Upvotes: 0
Views: 1388
Reputation: 585
You may want to get the top most view controller currently showing in your app. You can do this by retrieving the top most view controller when your singleton wants to display an error.
class AlertHelper {
static func showAlertWrapper(alertTitle: String, alertMessage: String) {
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert);
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil);
alertController.addAction(okAction);
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
// viewController should now be your topmost view controller
viewController.present(alertController, animated: true, completion: nil);
}
}
}
And call your showAlertWrapper:
AlertHelper.showAlertWrapper(alertTitle: "Error", alertMessage: self.genericError)
Upvotes: 1
Reputation: 2056
A workaround and maybe swiftier way would be to have the showAlertWrapper
in the UIViewController:
extension UIViewController {
func showAlertWrapper(title: String, message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert);
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil);
alertController.addAction(okAction);
present(alertController, animated: true, completion: nil);
}
}
Then you would just do
DispatchQueue.main.async {
viewController.showAlertWrapper(title: "Error", message: self.genericError)
}
Upvotes: 1