Why cancleButton of UIActionSheet becomes the first button on iOS7 device [duplicate] - swift

This question already has answers here:
UIActionSheet in swift puts Cancel button top in iOS 7
(2 answers)
Closed 7 years ago.
I ran my app on iPhone5s iOS7. The indexes of buttons are wrong, cancleButton becomes the first button. I am confused that when I tap the background, it opens the album. I don't know why. So strange.
图片在这里
This is my code.
func actionsheetInIOS8Early() {
let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "cancle", destructiveButtonTitle: nil)
actionSheet.addButtonWithTitle("album")
if UIImagePickerController.isSourceTypeAvailable( UIImagePickerControllerSourceType.Camera) {
actionSheet.addButtonWithTitle("camera")
}
actionSheet.showInView(self.view)
}

When you add
let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "cancle", destructiveButtonTitle: nil)
this line it will add Cancel button to index 0 and then after it will add your buttons
actionSheet.addButtonWithTitle("album")
if UIImagePickerController.isSourceTypeAvailable( UIImagePickerControllerSourceType.Camera) {
actionSheet.addButtonWithTitle("camera")
}
Album button at index 1 & Camera at index 2
So If you want Cancel button at last index then you need to add like
actionSheet.addButtonWithTitle("Cancel")
after adding your button for Album and Camera.

Try this
let optionMenu = UIAlertController(title: "Title", message: "message", preferredStyle: .ActionSheet);
if UIImagePickerController.isSourceTypeAvailable( UIImagePickerControllerSourceType.Camera){
let cameraAction = UIAlertAction(title: "Camera", style: .Default, handler: {
(alert: UIAlertAction) -> Void in
// do something
})
optionMenu.addAction(cameraAction);
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: {
(alert: UIAlertAction) -> Void in
print("Cancelled")
})
optionMenu.addAction(cancelAction);
self.presentViewController(optionMenu, animated: true, completion: nil);
If u add cancel button as above, cancel button will shown at the end of the AlertController

Related

Change UILabel Text via UIAlertAction

I want to have an alert action change the text of a UILabel in my View. Code below:
#IBAction func statusChange(_ sender: UIButton){
let playalert = UIAlertController(title: "OPERATION: \(sender.accessibilityIdentifier!) NOT POSSIBLE", message: "Convert op to PLAY mode to proceed", preferredStyle: .alert)
let recordalert = UIAlertController(title: "OPERATION: \(sender.accessibilityIdentifier!) NOT POSSIBLE", message: "Convert op to STOP mode to proceed", preferredStyle: .alert)
let statechangealert = UIAlertController(title: "OPERATION: \(sender.accessibilityIdentifier!) WILL NOW PROCEED", message: "", preferredStyle: .alert)
let stopAction = UIAlertAction(title: "Convert", style: .default, handler: { action in
self.statusDVR.text = "STOP"//"\(sender.accessibilityIdentifier!)"
})
let continueAction = UIAlertAction(title: "Continue", style: .default, handler: { action in
self.statusDVR.text = ""//"\(sender.accessibilityIdentifier!)"
})
let returnAction = UIAlertAction(title: "Return", style: .default, handler: { action -> Void in
})
playalert.addAction(stopAction)
playalert.addAction(returnAction)
recordalert.addAction(stopAction)
recordalert.addAction(returnAction)
statechangealert.addAction(continueAction)
//record was tapped, check if DVR stopped first
if (sender.tag == 5 && pwrStat == true ) {
//if not stopped send alert
if statusDVR.text != "STOP" {
self.present(recordalert, animated:true, completion: nil)
//if user tapped returned action
if statusDVR.text != "STOP" {
self.present(statechangealert, animated:true, completion: nil)
} else {
return
}
} else {
statusDVR.text = "RECORD"
}
The stopAction should convert a UILAbel called statusDVR in the view controller, but it doesn't do it.
I haven't tried implementing the other Actions yet, because I am stuck trying to figure out why my UILabel's text won't change. Thank you for any help :)
First of all, this code makes no sense:
if statusDVR.text != "STOP" {
self.present(recordalert, animated:true, completion: nil)
if statusDVR.text != "STOP" {
self.present(statechangealert, animated:true, completion: nil)
That code tries to present two alerts at the same time. That is illegal.
I think you think that when you say
self.present(recordalert, animated:true, completion: nil)
...your code magically comes to a stop while the user interacts with the alert and then proceeds after the user dismisses the alert. That’s not the case. Your code never magically stops; it just keeps right on going.
As for the actual question you asked about, the problem is simply that what you're doing is illegal:
playalert.addAction(stopAction)
playalert.addAction(returnAction)
recordalert.addAction(stopAction)
recordalert.addAction(returnAction)
No! You cannot take one UIAlertAction and somehow magically "share" it between two different UIAlertControllers. Every UIAlertController needs UIActions that belong to it alone. In other words, do not call addAction on the same UIAlertAction twice.
Just to demonstrate more simply, try running this code:
let action1 = UIAlertAction(title: "Test", style: .default) {
_ in print("test")
}
let alert1 = UIAlertController(title: "Hello", message: nil, preferredStyle: .alert)
let alert2 = UIAlertController(title: "Hello2", message: nil, preferredStyle: .alert)
alert1.addAction(action1)
alert2.addAction(action1)
self.present(alert1, animated: true, completion: nil)
The alert appears, you tap the Test button, the alert disappears — but nothing prints in the console. Now comment out the next to last line:
// alert2.addAction(action1)
... and run the code again. This time, when you tap Test, "test" appears in the console.

UIAlertController Crash Error [duplicate]

This question already has answers here:
UIAlertController is Crashed (iPad)
(11 answers)
Closed 4 years ago.
Here is my code
let selectRoute = UIAlertController(title: "Select a Route", message: "Please select the route you want to create your trip on", preferredStyle: .actionSheet)
let route1 = UIAlertAction(title: "Route 1", style: .default) { (action) in
self.reminder()
self.routeID = 1
self.tableView.reloadData()
}
let route2 = UIAlertAction(title: "Route 2", style: .default) { (action) in
}
selectRoute.addAction(route1)
selectRoute.addAction(route2)
if let popoverPresentationController = selectRoute.popoverPresentationController {
popoverPresentationController.sourceView = self.view
popoverPresentationController.sourceRect = self.view.bounds
}
self.present(selectRoute, animated: true, completion: nil)
When I run this, the actionSheet just appears just over the Navigation Controller really small, anyone know a fix?
On iPad the alert will be displayed as a popover using the UIPopoverPresentationController, it requires you define an anchor point for the presentation of the popover using either a sourceView and sourceRect or a barButtonItem.
To support iPad, include this code:
alertController.popoverPresentationController?.sourceView = self.view
alertController.popoverPresentationController?.sourceRect = self.myButton.frame
self.presentViewController(alertController, animated: true, completion: nil)
here is an example:
Suppose you have a button and you are going to show alert controller below of the button:
#IBOutlet weak var myBtn: UIButton!
let alertController = UIAlertController(title: "title :)", message:"message...", preferredStyle: .actionSheet)
let defaultAction = UIAlertAction(title: "cancel", style: .cancel, handler: nil)
let deleteAction = UIAlertAction(title: "delete", style: .destructive) { (action: UIAlertAction) in
//Do something
}
let addAction = UIAlertAction(title: "...", style: .default) { (action) in
//do something
}
alertController.addAction(addAction)
alertController.addAction(deleteAction)
alertController.addAction(defaultAction)
alertController.popoverPresentationController?.sourceRect = self.myBtn.frame
alertController.popoverPresentationController?.sourceView = self.view
self.present(alertController, animated: true, completion: nil)
If you are displaying the action sheet after the user makes a selection on a cell within a UITableView. you can use this code:
alertController.popoverPresentationController.sourceView = cell
alertController.popoverPresentationController.sourceRect = cell.bounds

UIAlertController - Order of actions [duplicate]

This question already has answers here:
Unable to choose order of buttons in UIAlertController
(2 answers)
Closed 5 years ago.
I wanna show alert window by pressing on button. Usual thing. But I'm confused that I try to show button "Awesome" at first, but always "Cancel" button stay the first. How can I fix it?
let alert = UIAlertController(title: "Hello world", message: "Testing", preferredStyle: .alert)
let action = UIAlertAction(title: "Awesome", style: .default){(_) in print("Awesome")}
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addTextField(configurationHandler: nil)
alert.addAction(action)
alert.addAction(cancel)
alert.actions.forEach( { (action) in print( action.title! ) } )
present(alert, animated: true, completion: nil)
Irregular order of buttons
Changing the order will not work as default position of cancel button is left.
Change the action style for cancel button type to UIAlertActionStyleDefault instead of UIAlertActionStyleCancel.
Try like this, it will work for you.
let alertController = UIAlertController(title: "", message: "", preferredStyle: UIAlertControllerStyle.alert)
let destructiveAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default) {
(result : UIAlertAction) -> Void in
}
let okAction = UIAlertAction(title: "Awesome", style: UIAlertActionStyle.default) {
(result : UIAlertAction) -> Void in
}
alertController.addAction(destructiveAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)

I need to create like a pop up menu where I can change data in a collection view when the collection view cell is pressed.

Basically, the question says it all. I thought about an alert but i need to actually have a text box inside and be able to save the text to a label. Any ideas on what I should use in this? I don't want to create a new view controller into a navigation. I just simply want a pop up view to open and close as needed.
All suggestions are greatly appreciated. Thanks!
You can add a textfield in your alertController.
Please refer to this answer https://stackoverflow.com/a/33000328/1754559
let alertController = UIAlertController(title: "Your alert", message: "", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default, handler: {
alert -> Void in
guard let textField = alertController.textFields?[0] as UITextField else { return }
yourLabel.text = textField.text
})
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: {
(action : UIAlertAction!) -> Void in })
alertController.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Whatever"
//Other textField configurations
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)

Why isn't my user alert code in Swift working as intended

I have a reset button in my app. I've coded it so that if users tap on this to reset the app they are presented with a user alert first. This alert provides info and offers two choices: (1) Cancel, (2) Continue.
The idea is that if they tap on Cancel the game won't reset. But if they tap on Continue, the game will reset.
ISSUE 1
At present, when the user taps on the reset button, the game is reset immediately before the alert displays. After the alert does display, if they tap 'Cancel' nothing more happens, but if they tap 'Continue' the game is reset again!
So, on the face of it the alert buttons work as they should - it's just that tapping the Reset icon already actions the reset before the alert appears.
ISSUE 2
My alert code caters for iOS 8 and above users as well as pre-iOS 8 users. How do I alter this part of the code to also offer pre-iOS 8 users the ability to either 'Cancel' or 'Continue'? At present they just get a 'Continue' option.
My code for the alerts is below:
#IBAction func buttonResetGame(sender: UIButton) {
if #available(iOS 8.0, *) {
let alert = UIAlertController(title: "Info", message: "This will reset your score and questions.", preferredStyle: UIAlertControllerStyle.Alert)
// add the Continue button and action
alert.addAction(UIAlertAction(title: "Continue", style: UIAlertActionStyle.Destructive, handler: {action in
// do this...
self.ResetGame()
}))
// add the Cancel button and action
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}else{
// For pre-iOS 8 users
let alert = UIAlertView()
alert.title = "Info"
alert.message = "This will reset your score and questions."
alert.addButtonWithTitle("Continue")
alert.show()
}
ResetGame()
}
If it's relevant, my code for resetting the game is below:
func ResetGame() {
PlaySoundReset()
score = 0
totalquestionsasked = 0
SaveScore()
LoadScore()
}
Remove the extra ResetGame() call after your if/else:
#IBAction func buttonResetGame(sender: UIButton) {
if #available(iOS 8.0, *) {
let alert = UIAlertController(title: "Info", message: "This will reset your score and questions.", preferredStyle: UIAlertControllerStyle.Alert)
// add the Continue button and action
alert.addAction(UIAlertAction(title: "Continue", style: UIAlertActionStyle.Destructive, handler: {action in
// do this...
self.ResetGame()
}))
// add the Cancel button and action
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}else{
// For pre-iOS 8 users
let alert = UIAlertView()
alert.title = "Info"
alert.message = "This will reset your score and questions."
alert.addButtonWithTitle("Continue")
alert.show()
}
ResetGame() //remove this line ? You are calling the RestGame func...
}
For the second part of your question, you need to set the delegate of the alert view to 'self' or whatever, then implement UIAlertViewDelegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex NS_DEPRECATED_IOS(2_0, 9_0);
Where the button index will give you each button i.e. 0 and 1.