swift - dismissing view controller from UIAlertController action prevents view controller from deiniting - swift

on a press of the close button I'm running this code
let alert = UIAlertController(title: "Hey!", message: "What to do?", preferredStyle: UIAlertControllerStyle.actionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default, handler: { [weak self]_ in
self?.alert.dismiss(animated: true)
})
let closeAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.default, handler: {[weak self] _ in
self?.dismiss(animated: true, completion: nil)
})
alert.addAction(cancelAction)
alert.addAction(closeAction)
self.present(alert, animated: true)
If the user presses on the close action, the view controller (self) will not deinit.

The solution is to keep a reference of the UIAlertContorller on the view controller and nullify it before closing the view controller.
self.alert = UIAlertController(title: "Hey!", message: "What to do?", preferredStyle: UIAlertControllerStyle.actionSheet)
and
let closeAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.default, handler: {[weak self] _ in
self?.alert = nil
self?.dismiss(animated: true, completion: nil)
})

Related

How to execute a block of code right after UIAlertController was dismissed

Is there a way to execute a block of code on dismissing UIAlertController without subclassing it or involving UIAlertActions?
I need to safely dispose an observable binded to alert's textfiled on its dismissal.
I think that you must to use the alert action, but if you want, you can mix with completion, like this
func showAlertMessageCompletion(titleStr:String, messageStr:String, completion: #escaping ((Bool) -> Void)) {
let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "Aceptar", style: .default) { (_) in
completion(true)
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
You need to add handler to alert action button.
let alertController = UIAlertController(title: "Alert title", message: "Message to display", preferredStyle: .alert)
// Create OK button
let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in
// Code in this block will trigger when OK button tapped.
print("Ok button tapped");
}
alertController.addAction(OKAction)
// Create Cancel button
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction!) in
print("Cancel button tapped");
}
alertController.addAction(cancelAction)
// Present Dialog message
self.present(alertController, animated: true, completion:nil)

variable 'alert' is written to, but never read

I have an alert-box, which returns a number of warnings that I'm having trouble, getting rid of.
let alert = UIAlertController(title: "Delete the group?", message: "The group is removed permanently", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { [weak alert] (_) in
self.dismiss(animated: true, completion: nil)
}))
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
// Perform the serverside action here and dismiss
}))
self.present(alert, animated: true, completion: nil)
Both addAction-lines returns a "Variable 'alert' is written to, but never read"-warning. I don't understand, since I use it in the "present"-line in the same scope.
Any ideas?
I have all my alerts in a separate class like so;
class AlertViewController {
func someAlert(with title: String?, message: String?, viewController: UIViewController) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let someAction = UIAlertAction(title: "Action Title", style: .default) { (_) in
//Perform your action here
}
alertController.addAction(someAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
viewController.present(alertController, animated: true, completion: nil)
}
}
If you use the style: .cancel it will automatically dismiss the alert. Furthermore, as a better UX, including this .cancel will allow the user to tap anywhere on the view to dismiss the alert as well.
You can call this action where needed like so;
AlertViewController.someAlert(with: "Title", message: "Message", viewController: self)
Self is the UIViewController you wish to present upon.

How to place my App Icon into an iOS alert window

I want to place my app icon into an alert controller above the alertTitle - same as for the alert that opens if an app review is called by SKStoreReviewController.requestReview().
I have not found any documentation about it.
So, what to do with the code below to let the App Icon appear?
let alertController = UIAlertController(title: alertHeaderText, message: alertText, preferredStyle: UIAlertController.Style.alert)
let option1: UIAlertAction = UIAlertAction(title: "text", style: .default, handler: {
(action) in
// some code
})
let option2: UIAlertAction = UIAlertAction(title: "text", style: .default, handler: {
(action) in
// some code
})
alertController.addAction(option1)
alertController.addAction(option2)
self.present(alertController, animated: true, completion: nil)

How to disable/stop (showLoginAlert) function from appearing?

I have login alert connected to UIViewController called Intro the alert show up in home screen and in all tabBar views when the user click in one of them, the alert prevent user from using the app unless he sign up. I want to stop the alert from showing because I'm implementing it somewhere else.
I tried to delete/comment the code but that resulted in a lot of errors showing
// MARK: - SHOW LOGIN ALERT
func showLoginAlert(_ mess:String) {
let alert = UIAlertController(title: APP_NAME,
message: mess,
preferredStyle: .alert)
let ok = UIAlertAction(title: "Login", style: .default, handler: { (action) -> Void in
let aVC = self.storyboard?.instantiateViewController(withIdentifier: "Intro") as! Intro
self.present(aVC, animated: true, completion: nil)
})
alert.addAction(ok)
let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })
alert.addAction(cancel)
present(alert, animated: true, completion: nil)
}
// MARK: - FIRE A SIMPLE ALERT
func simpleAlert(_ mess:String) {
let alert = UIAlertController(title: APP_NAME,
message: mess, preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in })
alert.addAction(ok)
present(alert, animated: true, completion: nil)
}

Open a new view controller after login alert swift 2.0

I am trying to change view controller if the login is successful but I am unsure how to do this. This is what i have tried so far. Thanks in advance!
#IBAction func signinaction(sender: AnyObject) {
let user = self.usernamefield.text!
ref.authUser(emailfield.text, password: passwordfield.text, withCompletionBlock: { error, authData in
if error != nil
{
let alert = UIAlertController(title: "Error", message: "Enter Email and Password.", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
print("can not sign in")
}
else
{
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewName:NSString = "NewView"
let vc = storyboard.instantiateViewControllerWithIdentifier(viewName as String) as! HomeViewController
let uid = authData.uid
print("Success with user: \(uid)")
let alert = UIAlertController(title: "Success", message: "Welcome \(user)", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(action)
self.navigationController?.pushViewController(vc as HomeViewController, animated: true)
}
})
}
Assuming that the view controller all of this is in is contained in a navigation controller, what you have should be working fine. Note, however that you're creating an alert you never show. My guess is that you want to display the success alert and then open the new view controller, something like:
let alert = UIAlertController(title: "Success", message: "Welcome \(user)", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default) { _ in
self.navigationController?.pushViewController(vc, animated: true)
}
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
If this still isn't working, I'd make sure the current view controller is actually displayed in a navigation controller.
Looks like you just need to add the navigation code inside of the alert action. Currently you have the handler parameter set to nil
this
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
becomes this
let alertAction = UIAlertAction(title: "Ok", style: .Default) { (action) -> Void in
self.navigationController?.pushViewController(vc as HomeViewController, animated: true)
}