UIAlertController is disappearing automatically after short time - swift

If a textfield is empty, I would like to make an UIAlertController to remind, that something has to be filled out in the textfield. Now I have the following code:
#IBAction func saveDetails(segue: UIStoryboardSegue) {
let dController = segue.source as? EntryTableViewController
if let text = dController?.bezeichnungTextField.text, text.isEmpty {
let alert = UIAlertController(title: "No description", message: "Please fill out description", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "OK", style: .default)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}else {
guard let menge = dController?.mengeTextField.text, let bezeichnung = dController?.bezeichnungTextField.text, let kategorie = dController?.categoryButtonOutlet.titleLabel?.text else {return}
self.saveItem(menge: menge, bezeichnung: bezeichnung, kategorie: kategorie)
self.tableView.reloadData()
}
}
Now actually it works when I press the button to return to the first controller. But the UIAlertController only appears for a very short moment and then disappears automatically. Is there a mistake in my code or isn't it possible to call the UIAlertController on a unwind segue?
Thank you for your help

You just show the alert controller and then immediately unwind. The solution is to check for the empty textfield before unwinding.
Make IBAction for your button then check the textfield if it is empty and then perforn your segue programmatically.

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.

how to add a password to a button event which cause the event to proceed or fail

I have a Xcode project which is a questionnaire, that has a few questions in and buttons that pass the data selected from one view to the other using segue tags.
At the end of the questionnaire I have a show data button in which will take the admin to the page with the data on as a whole, my issue is anyone can trigger the show data event and I was wondering how would I go about adding a password so that only the admin can see the data.
I've looked online and haven't seen anything that relates to what I need to happen, most things online go over creating a sign up page.
#IBAction func DataReveal(_ sender: UIButton)
{
ID = ID2.text
date = date2.text
Answer1 = answ1.text
Answer2 = answ2.text
}
self.performSegue(withIdentifier: "Link6", sender: self)
}
This takes the results from the other pages and passes them to the page that has the show data button, I just need to add password protection to it so only the password holder can see the data.
You need to Show UIAlert Action with textfield for pick password from user and match text with your password from Coredata,keychain or with API whatever you want.
UIAlert with textfield code is
let alertController = UIAlertController(title: "Test Title", message: "", preferredStyle: .alert)
alertController.addTextField { textField in
textField.placeholder = "Enter Password"
textField.isSecureTextEntry = true
}
let confirmActionBtn = UIAlertAction(title: "OK", style: .default) { [weak alertController] _ in
guard let alertController = alertController, let textField = alertController.textFields?.first else { return }
print("Password is \(String(describing: textField.text))")
// Just compare Entered String in textfield with your original password password
//if password is matched push or segue your required controller
}
alertController.addAction(confirmActionBtn)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)

swipe tableViewCell to delete an item

I want to delete a Unit from my Core Data Application. When user presses delete button on the Cell, I present a warning.
the code was
let alert = UIAlertController(title: "Warning!", message: "Are you sure to delete \"\(currentUnit)\" and all of its containing objects?", preferredStyle: .Alert)
I wanted to update the warning message with the objects count so I wrote
currentUnitObjectsCount = getSelectedUnitObjectsCount() //Which connects to database and returns just an integer
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete",handler: { (action, indexPath) -> Void in
let currentUnit = self.units[indexPath.row].title!
let alert = UIAlertController(title: "Warning!", message: "Are you sure to delete \"\(currentUnit)\" and all of its \(currentUnitObjectsCount) containing objects?", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: .Default) /* handler: { (action : UIAlertAction) -> Void in */ { (action : UIAlertAction) in
if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext{
let unitToDelete = self.fetchResultController.objectAtIndexPath(indexPath) as! Unit
managedObjectContext.deleteObject(unitToDelete)
do{
try managedObjectContext.save()
}catch{
print(error)
}
}
self.checkUnits()
}
let noAction = UIAlertAction(title: "No", style: UIAlertActionStyle.Default, handler: {
(action : UIAlertAction!) -> Void in
tableView.reloadData() //to return the tableView to its normal view
})
alert.addAction(yesAction)
alert.addAction(noAction)
self.presentViewController(alert, animated: true, completion: nil)
})
deleteAction.backgroundColor = UIColor.redColor()
return [editAction]
}
Now when i swipe the tableViewCell, it swipes but the delete button does not appear but when I tap the Delete button position in the swiped cell, the warning appears which means the button is there but I cant see it.
returning the code to the first style every thing works fine, but the second one acts very strange.
When I put this line of code
currentUnitObjectsCount = getSelectedUnitObjectsCount() //Which connects to database and returns just an integer
just after the the
let deleteAction = ...
currentUnitObjectsCount = getSelectedUnitObjectsCount()
let currentUnit = self.units[indexPath.row].title!
.
.
.
and swipe a cell, rows of the table disappear
I dont find why these happen.

How to unwind segue with alert view in Swift?

I have several View Controllers. I need to return to the first View Controller if the Alert View is confirmed. This is how I would do it without the unwind Segue:
#IBAction func unwindToDelete ( segue: UIStoryboardSegue ) {
let alertView = UIAlertController(title: "Delete?", message: "Are you sure you wante to delete?", preferredStyle: .ActionSheet)
let deleteAction = UIAlertAction (title: "Delete", style: .Destructive ) { alertAction in
self.deleteChoice = true
}
let cancelAction = UIAlertAction (title: "Cancel", style: .Cancel ) { alertAction in
}
alertView.addAction(deleteAction)
alertView.addAction(cancelAction)
self.presentViewController(alertView, animated: true, completion: nil)
}
But if I do that, in this code it crashes because of the last line of code.
This is the error:
2015-04-30 14:59:45.605 PhotosCollection[4624:182995]
popToViewController:transition: called on <UINavigationController 0x7a67aeb0>
while an existing transition or presentation is occurring; the navigation
stack will not be updated.
How can I complete the Alert View while being able to unwind segue.
Thank you
You are putting up the alert after the unwind has happened. You want to be able to not perform the unwind at all if the user chooses to cancel the delete. I would suggest the following:
Instead of wiring the unwind segue to your delete button, instead connect it to the view controller icon at the top of the view controller so that you can call the unwind programmatically. This answer shows you how to do that:
Setting up the unwind segue.
Give the unwind segue an identifier such as "doUnwind".
In the #IBAction for your delete button, put up the alert asking the user if they really want to delete.
In the handler for the delete button, call the unwind segue programmatically.
#IBAction func deleteButton (button: UIButton) {
let alertView = UIAlertController(title: "Delete?", message: "Are you sure you wante to delete?", preferredStyle: .ActionSheet)
let deleteAction = UIAlertAction (title: "Delete", style: .Destructive ) { alertAction in
self.performSegueWithIdentifier("doUnwind", sender: self)
}
let cancelAction = UIAlertAction (title: "Cancel", style: .Cancel ) { alertAction in
}
alertView.addAction(deleteAction)
alertView.addAction(cancelAction)
self.presentViewController(alertView, animated: true, completion: nil)
}

Creating a pop up dialog alert

I'm trying to create a popup uialert sort of to create a confirmation box. I have a button in ViewControllerTwo and when pressed navigates back to ViewControllerOne, however I want to create a popup message that asks to confirm (Yes or No) if I really want to navigate to ViewControllerOne. If yes it goes backs to ViewOne, if no it stays on the ViewTwo. How do I do this?
#IBAction func showAlertTapped(sender: AnyObject) {
//Create the AlertController
let myAlertController: UIAlertController = UIAlertController(title: "Hey..!", message: "Are You sure to Do some stuff??", preferredStyle: .Alert)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//Do some stuff
}
myAlertController.addAction(cancelAction)
//Create and an option action
let nextAction: UIAlertAction = UIAlertAction(title: "Next", style: .Default) { action -> Void in
let mainStoryboard = UIStoryboard(name: "Storyboard", bundle: NSBundle.mainBundle())
let vc : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier("vcMainLogin") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
myAlertController.addAction(nextAction)
//Present the AlertController
self.presentViewController(myAlertController, animated: true, completion: nil)
}