How to cancel a segue in certain conditions (if/else)? [duplicate] - ios

This question already has answers here:
Conditional Segue in Swift
(2 answers)
Closed 7 years ago.
I am creating an app. In a certain view, there are several text fields in which the user inputs numbers, then presses a button, and is transported into the next view controller.
How do I make it so if a person taps the button, and one or more text fields are empty, the segue cancels?
Here is my code for that area so far:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if saveButton === sender {
let name = nameTextField.text ?? ""
// Set the meal to be passed to MealListTableViewController after the unwind segue.
meal = Meal(name: name)
}
if calcButton === sender {
if weightInKilos.text == "" && percentOfDehydration.text == "" && ongoingLosses.text == "" && factor.text == "" {
let alertController = UIAlertController(title: "Fields were left empty.", message:
"You left some fields blank! Please make sure that all fields are filled in before tapping 'Calculate'.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
else {
let DestViewController: ftrViewController = segue.destinationViewController as! ftrViewController
let weightInt: Int? = Int(weightInKilos.text!)
let dehydrationInt: Int? = Int(percentOfDehydration.text!)
let lossesInt: Int? = Int(ongoingLosses.text!)
let factorInt: Int? = Int(factor.text!)
let lrs24Int = (30 * weightInt! + 70) * factorInt! + weightInt! * dehydrationInt! * 10 + lossesInt!
let lrsPerHourint = lrs24Int / 24
DestViewController.lrsHr = "\(lrsPerHourint)"
DestViewController.lrs24Hrs = "\(lrs24Int)"
}
}
}

You must check everything you need BEFORE calling the segue.
So, the user write the answers, you check if everything is ok, IF, its ok, do the segue, else, you alert the user and ask for retype the info.
Got it?

Related

Im trying to get the data entered to do calculation and display in a label

I am trying to get The Information that is added to display in a label on the main screen. I want it to calculate the profit but i get the error " Value of type 'String' has no member 'text' "
#IBAction func addButtonTapped(_ sender: Any) {
let alert = UIAlertController(title: "Product Information", message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: { (itemTextField) -> Void in
itemTextField.placeholder = "Item"
})
alert.addTextField(configurationHandler: { (priceTextField) -> Void in
priceTextField.placeholder = "Price"
})
alert.addTextField(configurationHandler: { (salePriceTextField) -> Void in
salePriceTextField.placeholder = "Sale Price"
})
alert.addAction(UIAlertAction(title: "Add", style: .default) { (action) in
let item = alert.textFields?[0].text ?? ""
let price = alert.textFields?[1].text ?? ""
let salesPrice = alert.textFields?[2].text ?? ""
let itemPriceLabel = Double(price.text!)
let salePriceLabel = Double(salesPrice.text!)
if itemPriceLabel != nil && salePriceLabel != nil {
let profitValue = Double (itemPriceLabel! - salePriceLabel!)
ProfitLabel.text = profitValue
}
let product = Product(item: item, price: price, salesPrice: salesPrice)
self.addProduct(product)
})
self.present(alert, animated: true, completion: nil)
storeData()
}
Your price and salesPrice variables are already string only. But you’ve tried to access text field in those variables which is not present in String class in the next statement.
let itemPriceLabel = Double(price)
let salePriceLabel = Double(salesPrice)
And assign your value as follows.
ProfitLabel.text = String(profitValue)
Basically, both price and salesPrice are already Strings (because they took the text from the labels), not labels.
All you need to do is convert them to straight to doubles, no need for .text.
So instead of:
let itemPriceLabel = Double(price.text!)
let salePriceLabel = Double(salesPrice.text!)
Do:
let itemPriceLabel = Double(price)
let salePriceLabel = Double(salesPrice)
There are a few mistakes in the alert action and the naming of the variables is confusing, replace it with
alert.addAction(UIAlertAction(title: "Add", style: .default) { _ in
let itemText = alert.textFields?[0].text ?? ""
let priceText = alert.textFields?[1].text ?? ""
let salesPriceText = alert.textFields?[2].text ?? ""
if let price = Double(priceText),
let salesPrice = Double(salesPriceText),
!itemText.isEmpty {
let profitValue = price - salesPrice
ProfitLabel.text = String(profitValue)
let product = Product(item: itemText, price: price, salesPrice: salesPrice)
self.addProduct(product)
} else {
print("Enter something in 'item' and enter numeric values in 'price' and 'sales price'")
// add error handling
}
}

Cant get uIAlertAction to work textfield will only read first and last element

Im doing an IOS contact app and I want the user to able to change there quick information from an alert my problem is that I cannot get my alertAction to read anything beside the first and last element
let add = UIAlertAction(title: "Add", style: .default) { _ in
guard
let name = alert.textFields?.first?.text,
let address = alert.textFields?.first?.text,
let state = alert.textFields?.first?.text,
let city = alert.textFields?.first?.text,
let zip = alert.textFields?.first?.text,
let phoneString=alert.textFields?.last?.text,
let phone = Int(phoneString)
else { return }
I know that alert.textField?.first.text returns the first element and alert.textField?.last.text returns my last element ,so what ever goes in my name and phone textField is good , but how can I return the elements that go in to my address , state , city and zip text fields?
You can add tag to each of your textFields. And then utilize it, you can enumerate your textFields in your alert object. For example:
let alert = UIAlertController(title: "Add New Name", message: "", preferredStyle: .alert)
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Name"
textField.tag = 0
}
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Address"
textField.tag = 1
}
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter State"
textField.tag = 2
}
let saveAction = UIAlertAction(title: "Save", style: .default, handler: { _ -> Void in
guard let name = alert.textFields?.filter({ $0.tag == 0 }).first?.text,
let address = alert.textFields?.filter({ $0.tag == 1 }).first?.text,
let state = alert.textFields?.filter({ $0.tag == 2 }).first?.text else { return }
/////
})
alert.addAction(saveAction)
self.present(alert, animated: true, completion: nil)
OR
let name = alert.textFields?[0].text ?? ""
let address = alert.textFields?[1].text ?? ""
let state = alert.textFields?[2].text ?? ""
You can add multiple textfields inside a UIAlertController. UIAlertController has a property "textFields" which is basically a array of all added TextFields.
You can add a textfield using this code -
let alert = UIAlertController(title: "Alert", message: "Hi", preferredStyle: .alert)
alert.addTextField { (textFieldName) in
// Configure it here
}
alert.addTextField { (textFieldAddress) in
}
alert.addTextField { (textfieldCity) in
}
The order in which you add the textFields ,will be same when you will access the textfields using "textField" property.

Swift - Warning when editing text fields and tapping buttons

I have a scroll view that adds UI elements programmatically, but a button that I've added seems to have a delay in response once tapped both in a simulator and on an iPhone 7 Plus I use to test on it. I'm not sure as to why. I also am getting warning messages each time a text field is edited as well. How do I resolve these issues? Below our the warning messages and some of my code.
Thank you for helping!
Button warning in log:
2017-04-20 14:49:35.087232-0500 HAEForMe[889:369946] Warning: Attempt to present <UIAlertController: 0x102642b00> on <AppName.UserSetupViewController: 0x10303dc00> which is already presenting <UIAlertController: 0x10243b9b0>
Textfield warning in log:
2017-04-20 16:00:56.105536-0500 HAEForMe[52504:6463817] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /Users/andrewzimmerman/Library/Developer/CoreSimulator/Devices/476B95C5-691C-43D0-98D8-EAC400F6A41A/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2017-04-20 16:00:56.106290-0500 AppName[52504:6463817] [MC]
Code:
//Begin UITextField Initialization
var inputFields = [UITextField]()
let textField = UITextField() // This continues until there are 10.
/*
AddFields - Adds UITextFields to the inputFields array.
*/
private func addFields()
{
inputFields.append(textField) // Done for all 10 fields.
}
/*
ViewDidLoad - Runs stated code when the view loads.
*/
override func viewDidLoad() {
super.viewDidLoad()
prepareScrollView() //If view is touched, keyboard is dismissed.
addFields() //Adds some UITextFields to an array.
managePages() //Adds images, textfields, and button to ScrollView
addDoneButtonOnKeyboard() //Adds a tool bar with the done button
}
/*
ManagePages - Adds all items required for Scroll View [Some code
is removed as it is irrelevant]
*/
private func managePages()
{
self.sideScrollView.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height)
let scrollViewWidth:CGFloat = self.sideScrollView.frame.width
let scrollViewHeight:CGFloat = self.sideScrollView.frame.height
//*!*!* EFFICIENCY IN QUESTION *!*!*
for (index,element) in inputFields.enumerated()
{
if(index == 0)
{
//Sets properties of UITextField
}
else if(index == 1)
{
//Sets properties of UITextField
}
// The else if statements continue on until index is 9
}
let getStartedButton = UIButton(frame: CGRect(x:((scrollViewWidth*5) + scrollViewWidth/2)-125, y: scrollViewHeight-175, width: 250, height: 99))
getStartedButton.setImage(UIImage(named: "GetStartedButton"), for: UIControlState.normal)
getStartedButton.addTarget(self, action: #selector(finishSetup), for: .touchUpInside)
//*!*!* EFFICIENCY IN QUESTION *!*!*
for fieldName in inputFields
{
self.sideScrollView.addSubview(fieldName)
}
self.sideScrollView.addSubview(getStartedButton)
self.sideScrollView.contentSize = CGSize(width:self.sideScrollView.frame.width * 6, height:self.sideScrollView.frame.height)
self.sideScrollView.delegate = self
}
/*
FinishSetup - Checks all fields for input, ensure they aren't blank
and uses them
*/
func finishSetup(sender: UIButton!) {
print("Finished setup button tapped, attempting to finalize setup.")
var firstName: String = ""
var lastName: String = ""
var dateOfBirthValue: String = ""
var dateFormatter: DateFormatter
var date: Date = Date()
var age:Double = 0.0
var weight: Double = 0.0
var height: String = ""
var factType: String = "" //Name Changed
var valueType: Int = 0 //Name Changed
for (index,fieldName) in inputFields.enumerated()
{
if(fieldName.text != " " && fieldName.text != "" && fieldName.text != nil)
{
/*
Goes through each field in the array via each and every index
and then uses if statements to pull the text value for use in
a database later on.
*/
}
else
{
//*!*!* EFFICIENCY IN QUESTION *!*!*
print("Presenting blank field alert.")
let alertController = UIAlertController(title: "Uh Oh!", message: "Looks like you left something blank, please make sure that you've filled every field out and try again.", preferredStyle: UIAlertControllerStyle.alert)
let okayAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.default) {
(result: UIAlertAction) -> Void in
print("User reacted to blank field alert.")
}
alertController.addAction(okayAction)
self.present(alertController, animated: true, completion: nil)
return
}
}
}

Swift 3 increment increment tab bar badge [duplicate]

#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}

Increment tab bar badge w/ UIAlertAction swift?

#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}

Resources