I'm quite new to Swift (and coding in general) and to this website.
I'm having a little bit of an issue now. In my app, I have an alert when a timer reaches 0. In that alert, there are 2 buttons. One says "Share" and the other says "Continue". I want to make it such that when a user taps "Continue", the next Storyboard will be shown to them. As of now, whatever button I press will dismiss the alert, but stay on the same Storyboard. (It also prints to the console which button I pressed, but of course that's just for me to see).
How do I go about doing this? Here is my code, in case anyone wants to know.
let alert = UIAlertController(title: "Time's Up!", message: "What would you like to do now?", preferredStyle: .Alert)
let firstAction = UIAlertAction(title: "Continue", style: .Default) { (alert: UIAlertAction!) -> Void in
NSLog("You pressed button one")
}
let secondAction = UIAlertAction(title: "Share", style: .Default) { (alert: UIAlertAction!) -> Void in
NSLog("You pressed button two")
}
alert.addAction(firstAction)
alert.addAction(secondAction)
presentViewController(alert, animated: true, completion:nil)
Try with this:
// Create the alert controller
var alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)
// Create the actions
var okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) {
UIAlertAction in
NSLog("OK Pressed")
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
var cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
//do whatever you want here
}
// Add the actions
alertController.addAction(okAction)
alertController.addAction(cancelAction)
// Present the controller
self.presentViewController(alertController, animated: true, completion: nil)
If you haven't already set your ViewControllerIdentifier:
You need to set the Identifier value that you can find on the right column
Here is the code that might help you. When you create a AlertController with actions, you can provide the actions and style of the button when you define them. In code below action is in the closure (Block) and style is defined as .Default or .Cancel
let alert = UIAlertController(title: "Time's Up!", message: "What would you like to do now?", preferredStyle: .Alert)
let firstAction = UIAlertAction(title: "Continue", style: .Default) { (alert: UIAlertAction!) -> Void in
// Action when you press button goes here
print("Here you show next storyboard item.")
// Code to push new ViewController. For example :
self.navigationController?.pushViewController(newVCInstance, animated: true)
}
let secondAction = UIAlertAction(title: "Share", style: .Default) { (alert: UIAlertAction!) -> Void in
print("Here you share things.")
// Code to share things.
}
let thirdAction = UIAlertAction(title: "Cancel", style: . Cancel) { (alert: UIAlertAction!) -> Void in
print("Just dismissing the Alert Controller.")
}
alert.addAction(firstAction)
alert.addAction(secondAction)
alert.addAction(thirdAction)
presentViewController(alert, animated: true, completion:nil)
Related
I have very strange bug with default Alert in my iOS app for iPad.
On it I have three buttons: one for camera, second for photo gallery and third is dismiss button. Alert is used to pick photos. Issue I have is sometimes, when I click on dismiss button on that alert, this type of code get's executed:
let loginVC = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginPageViewController
I'm not sure if this is exactly the code that get's executed, but it performs logout action and users get redirected to login screen.
Here's my code for Alert
func showPopover(uiView: UIView) {
let alertController = UIAlertController(title: nil, message: "Choose Photos", preferredStyle: .actionSheet)
let defaultAction = UIAlertAction(title: "Camera", style: .default, handler: { (alert: UIAlertAction!) -> Void in
self.view?.pickPhotoFromCamera()
})
let galleryAction = UIAlertAction(title: "Gallery", style: .default, handler: { (alert: UIAlertAction!) -> Void in
self.view?.pickPhotoFromLibrary()
})
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: { (alert: UIAlertAction!) -> Void in
(self.view as? UIViewController)?.dismiss(animated: true, completion: nil)
})
alertController.addAction(defaultAction)
alertController.addAction(galleryAction)
alertController.addAction(cancelAction)
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = uiView
popoverController.sourceRect = CGRect(x: uiView.bounds.midX, y: uiView.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []
}
(view as? UIViewController)?.tabBarController!.present(alertController, animated: true, completion: nil)
}
As you can see, my code in alert doesn't have any actions for logout, but sometimes such thing happens. Maybe someone had similar issues? What could be the reason for that?
If you need more information - let me know. Thanks in advance for your help!
First you don't need to write any code for a .cancel type action button to dismiss the presented alert view controller. Secondly, you can just use view to present the alert controller, no need to ask it's parent (tabBarController) to do it. Your code in the .cancel button dismiss the Login controller itself.
import UIKit
class LoginViewController: UIViewController {
func showPopover(uiView: UIView) {
let alertController = UIAlertController(title: nil, message: "Choose Photos", preferredStyle: .actionSheet)
let defaultAction = UIAlertAction(title: "Camera", style: .default, handler: { (alert: UIAlertAction!) -> Void in
self.pickPhotoFromCamera()
})
let galleryAction = UIAlertAction(title: "Gallery", style: .default, handler: { (alert: UIAlertAction!) -> Void in
self.pickPhotoFromLibrary()
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
alertController.addAction(galleryAction)
alertController.addAction(cancelAction)
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = uiView
popoverController.sourceRect = uiView.bounds
}
present(alertController, animated: true, completion: nil)
}
private func pickPhotoFromCamera() { }
private func pickPhotoFromLibrary() { }
}
try
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
The issue in cancelAction which dismiss the current view controller. set its style to cancel with no handler.
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
I don't want to change UILabel.appearance as it will apply to all labels.
How I can show UIAlertController that will look like below image?
Need to show bold button in the second position.
By default, when I am setting UIAlertActionStyle.cancel it shows it on the Confirm button in the first position.
It looks like this now:
I did some research but I didn't find any solution.
Swift 4.2/Swift 5
You need to set preferred action method,
//Create alertController
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
//Create and add the Confirm action
let confirmAction = UIAlertAction(title: "Confirm", style: .default, handler: { (action) -> Void in
//Do Something here...
})
alert.addAction(confirmAction)
//Create and add the Cancel action
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
//Do Something here...
})
alert.addAction(cancelAction)
// Set Preferred Action method
alert.preferredAction = confirmAction
self.present(alert, animated: true, completion: nil)
The output will be,
You need to add them to the alertView in the right order! If you want the order to change just add the confirm button second!
alert.addAction(cancelAction)
alert.addAction(confirmAction)
Instead of:
alert.addAction(confirmAction)
alert.addAction(cancelAction)
Sure, you can. Try this
let alertView = UIAlertController(
title: "Home",
message: "Are you sure for delete Reminder",
preferredStyle: .alert)
alertView.view.tintColor = .green
let confirmAction = UIAlertAction(title: "Confirm", style: .cancel) { (_) in
// Do confirm
}
alertView.addAction(confirmAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .default) { (_) in
// Do cancel
}
alertView.addAction(cancelAction)
self.present(alertView, animated: true, completion: nil)
I have a UIAlertController in which the options are populated from an array and are presented to the user. The user then selects an option from the alert. After this, I have a separate alert that provides the user with a confirmation message that has an okay button.
myAlert.addAction(UIAlertAction.init(title: item, style: .Default, handler: {
(UIAlertAction) in
self.chosenBusiness.append(businessNameData[item]!)
}))
self.presentViewController(myAlert, animated: true, completion: nil)
The code above gathers the data from the array and pushes it into actions in myAlert. The code above is inside of a for loop.
After this I use a function to retrieve the topmost view controller, and then push the next alert.
let top = topMostController()
let alertController = UIAlertController(title: "Location pinned", message: "You've successfully pinned this location, good work!", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) {
(result : UIAlertAction) -> Void in
print("OK")
}
alertController.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
top.presentViewController(alertController, animated: true, completion: {
_ in
})
The error I receive is:
Attempting to load the view of a view controller while it is
deallocating and is not allowed and may result in undefined behavior.
UIAlertController: 0x1535b1cd0.
Can someone help me with this?
I think this is what you are looking for. The second must be called with the dismissal action of the first. Also, anytime you work with UI, It is safer to use dispatch_async(dispatch_get_main_queue()) {
\\code }
than not if you are not positive you are currently on the main queue.
let firstAlertController = UIAlertController(title: "First", message: "This is the first message.", preferredStyle: UIAlertControllerStyle.Alert)
let secondAlertController = UIAlertController(title: "Second", message: "This is the second message.", preferredStyle: UIAlertControllerStyle.Alert)
let secondDismissAction = UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, completion: nil)
secondAlertController.addAction(secondDismissAction)
let firstDismissAction = UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default) {
UIAlertAction in
dispatch_async(dispatch_get_main_queue()) {
self.presentViewController(secondAlertController, animated: true, handler: nil)
}
}
firstAlertController.addAction(firstDismissAction)
self.presentViewController(firstAlertController, animated: true, completion: nil)
I am trying to popViewController to the previous View Controller in the navigation stack after an alertView. As of now, my program will not run the popViewController method, since the alertView is in the way, and brings up the error:
UINavigationController 0x17670900 while an existing transition or presentation is occurring; the navigation stack will not be updated.
How do I go about running the popViewController method after the user clicks OK from the alertView? Do I have to set a delegate which detects when the used clicks OK?
Here is my code:
//alertView after Picture saved
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
self.presentViewController(alertView, animated: true, completion: nil)
//go to previous controller using popViewController, doesnt work, brings up error message
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
You need to pop the view controller when user presses the Ok button from AlertView.
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "Ok", style: .Default) { (action) in
// pop here
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
}
alertView.addAction(OKAction)
self.present(alertView, animated: true, completion: nil)
You can put the "popViewControllerAction" inside an alert action like this.
func alertMethod() {
var okAlertController = UIAlertController(title: NSLocalizedString("Your title", comment: ""), message: "Your message", preferredStyle:
UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action - navController.popViewControllerAnimated(true)
}
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action
}
}
saveAlertController.addAction(okAction)
saveAlertController.addAction(cancelAction)
self.presentViewController(okAlertController, animated: true, completion: nil)
}
That should work, in that case the method gets called after the user presses a button...
I would like to create the following UIAlertAction:
#IBAction func buttonUpgrade(sender: AnyObject) {
let alertController = UIAlertController(title: "Title",
message: "Message",
preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
// ...
}
alertController.addAction(cancelAction)
}
I'm aware that an UIAlertController is initialized with a title, message, and whether it prefers to be displayed as an alert or action sheet.
When the button is pressed I would like to display the alert, but alert.show() doesn't work. Why doesn't my code work?
The main issue here is that UIAlertController (unlike UIAlertView) is a subclass of UIViewControlller, meaning it needs to be presented as such (and not via the show() method). Other than that, if you want to change to color of the cancel button to red, you have to set the cancel action's alert style to .Destructive.
This only works if you want the button to be red. If you want to change the colors of the buttons in the alert controller to arbitrary colors, this can only be done by setting the tintColor property on the alert controller's view property, which will change the tint color of all of its buttons (except those that are destructive). It should be noted that with the design paradigms that Apple has put in place, it isn't necessary to change the cancel button's color due to the implications of its having bolded text.
If you do still want the text to be red though, it can be done like this:
let alertController = UIAlertController(
title: "Title",
message: "Message",
preferredStyle: UIAlertControllerStyle.Alert
)
let cancelAction = UIAlertAction(
title: "Cancel",
style: UIAlertActionStyle.Destructive) { (action) in
// ...
}
let confirmAction = UIAlertAction(
title: "OK", style: UIAlertActionStyle.Default) { (action) in
// ...
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
presentViewController(alertController, animated: true, completion: nil)
Which produces the results you're after:
let alertController = UIAlertController(
title: "Title",
message: "Message",
preferredStyle: UIAlertControllerStyle.Alert
)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
// ...
}
let okayAction = UIAlertAction(title: "OK", style: .Default) { (action) in
// ...
}
alertController.addAction(okayAction)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true) {
// ...
}
var alertController = UIAlertController(title: "Alert", message:"Message", preferredStyle: UIAlertControllerStyle.Alert)
let confirmed = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
alertController.addAction(confirmed)
alertController.addAction(cancel)
self.presentViewController(alertController, animated: true, completion: nil)
Important is the last line "self.presentViewController" to actually show your alert.
Hope it works ;)