Better way to check for a Int in a textbox - ios

I am learning Xcode and creating a very simply program with a textbox(txt box) in which the user enters a value, a button (btnCalc) that performs a calculation, and a label (lblcalcdnumber) that shows the calc'd number. I have already selected Number Pad to be displayed as the dropdown keyboard but i want to check to make sure that if they enter anything other than a number that nothing happens. The code i have works but i feel like there should be a cleaner solution. Essential i want them to only enter Integers in the textbook.
// Mark: Actions
#IBAction func btnCalc(sender: UIButton) {
// let txtbox text beome int
let number1 = Int(txtBox.text!)
// let possibleInt convert mystring to int to check for nil, txtbox becomes OPTIONAL
let possibleInt = Int(txtBox.text!)
let number = 25
if possibleInt != nil {
let combinednumber = "\(Int(number1!) * number)"
lblCalcedNumber.text = combinednumber
}
else {
txtBox.text = ""
txtBox.placeholder = "Please Enter a Valid Number"
}
}

You can use if and let together to create an optional. If the value is not nil it will cast to possibleInt, otherwise, it will evaluate as false.
#IBAction func btnCalc(sender: UIButton) {
if let possibleInt = Int(txtBox.text!) {
let combinednumber = "\(possibleInt * 25)"
lblCalcedNumber.text = combinednumber
}
else {
txtBox.text = ""
txtBox.placeholder = "Please Enter a Valid Number"
}
}

Your variables 'number1' and 'possibleInt' have the same value, so you only need one of them for this section of code. Since 'number' is only used once it would be better to use the value itself rather than create a variable for it, however, if you use it elsewhere keep it as a variable so you only need to change your code in one spot. If you weren't using the possibleInt/number1 value inside the if statement, you could be even more efficient by doing if Int(txtBox.text!) != nil. Try this:
// Mark: Actions
#IBAction func btnCalc(sender: UIButton) {
let possibleInt = Int(txtBox.text!)
if possibleInt != nil {
let combinednumber = "\(possibleInt * 25)"
lblCalcedNumber.text = combinednumber
}
else {
txtBox.text = ""
txtBox.placeholder = "Please Enter a Valid Number"
}
}

Related

How to replace dictionary particular key value using Swift

I am implementing button click to add CollectionView Cell like a Tag UI. Here, I created TagModel class for maintaining TagId and validating each time the tag data available or not by using if items.contains(tag) == false {….} (It will avoid duplication into collection view). Now, I need to add one more validation into this, if items.contains(tag) == true need to check tagName and current selected values are same. if not same I need to replace that tag value. How to achieve this?
Tag Validation Code
func tagValidation(){
// Validate A
if let aValue = UserDefaults.standard.object(forKey: "a") as? [String:Any] {
let tag = TagModel(dict: aValue)
if items.contains(tag) == false { // how to check if true need to validate current value and already exists values are same. if same no need to replace or else need to replace value
items.append(tag)
}
}
}
First ViewController
#IBAction func saveAction(_ sender: Any) {
let tag = TagModel(tagId: 0, tagName: "test", tagStoreKey: "a")
tag.save()
self.dismiss(animated: true, completion: nil)
}
Something is not right with your equality operator: you are asking if two items are the same - and if they are the same then check if something in them is different :)
Try to search array with first method: if you find (and you will) any item matching the case continue with your work.
Something like this:
if let aValue = UserDefaults.standard.object(forKey: "a") as? [String:Any] {
let tag = TagModel(dict: aValue)
if items.contains(tag) == false {
items.append(tag)
} else if let existing = items.first(where: { $0 == tag}), existing.tagName != tag.tagName {
// replace item
let index = items.firstIndex(of: tag)!
items[index] = tag
}
}

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) When Characters Exceed

I know there are answers available regarding this exception but nothing is working for me.
My code was working fine where I have to convert the text of a textfield into Int, but now I noticed that when I enter more than 10 characters it crashes.
I have set character limit of those text fields to 11, but it is crashing on the last number with the error: Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
Here is the code
#IBAction func Qty_EndEdit(_ sender: Any) {
print("For Total Cost")
if QtyText.text != ""{
if UnitPriceText.text != "" {
TotalCostText.text = String((QtyText.text?.numberValue)! * (UnitPriceText.text?.numberValue)!)
}
}
}
#IBAction func UnitPrice_EndEdit(_ sender: Any) {
print("For Total Cost")
if QtyText.text != ""{
if UnitPriceText.text != "" {
TotalCostText.text = String((QtyText.text?.numberValue)! * (UnitPriceText.text?.numberValue)!)
// CRASHING ON THE ABOVE LINE
}
}
}
extension String {
var numberValue:Int? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self) as! Int
}
}
Your crash is related to the fact that Int multiplication cannot handle such numbers, use Double.
Both of your actions do the same thing, try to place code that will be reused inside a func.
You also need to look at optionals and how to use them. Here's an example.
func updateTotalCost() {
if let quantity = Double(QtyText.text ?? ""),
let unitPrice = Double(UnitPriceText.text ?? "") {
TotalCostText.text = String(quantity * unitPrice)
} else {
// ???
TotalCostText.text = ""
}
}
#IBAction func Qty_EndEdit(_ sender: Any) {
updateTotalCost()
}
#IBAction func UnitPrice_EndEdit(_ sender: Any) {
updateTotalCost()
}
I'll dissect some of it:
QtyText.text ?? "" -> If QtyText.text is nil, replace it with an empty string, otherwise use the value in QtyText.text
Double(QtyText.text ?? "") -> Build an Double from aString, which is guaranteed non-nil (since we forced it to be an emptyString`, even in the case the QtyText.text was nil)
This Double() constructor may, itself, return nil if the string passed to the constructor does not evaluate to a valid Double (for example, the String "abcd" cannot evaluate to an Double). Therefore, we wrap this in an if let statement to protect ourselves against the Double() constructor failing to build an Double from our String:
if let quantity = Int(QtyText.text ?? "")
This is telling the compiler:
Only evaluate this as true if what I'm placing in the quantity variable is not nil.
Finally, we chain two if statements with a comma:
if let quantity = Int(QtyText.text ?? ""),
let unitPrice = Int(UnitPriceText.text ?? "") {
Inside this part of the if statement, we'll be guaranteed that quantity and unitPrice both are valid Doubles , and that we can perform the calculation.
I’m not sure you’ll be please with the result of String(myDoubleNumber) but then you should look into number formatting to get what you want.

Not able to check the condition on submit button swift

Short description :
I am getting one value called UserValue. This will come from one response.And i have one Confirm button press method. In that each time i need to check whether the user entered amount is greater then UserValue amount.
but some time the value will be UserValue will be nill.That time it should not check whethere entered amount in text filed is greater than UserValue
Now here my code :
#IBAction func confirmButnClicked(_ sender: Any) {
print(UserValue)
let Mvalue = Double((UserValue.formattedAmount()))
let stringValue = Int(Mvalue!)
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}
Its working fine when i got some value in UserValue but when i get nill value here its crashing...How can i handle this:
let stringValue = Int(Mvalue!) // crash here
Thanks in advance !!
You are forcefully unwrapping the nil, Due to that its crashing.
Check the UserValue is nil or not. If not nil then do the comparison
#IBAction func confirmButnClicked(_ sender: Any) {
print(UserValue)
if let UserValue = UserValue {
if let Mvalue = Double((UserValue.formattedAmount())) {
if let stringValue = Int(Mvalue) {
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}
}
}
}
Instead of force casting MValue to Int you will get error when MValue is nil or anyother type content except integer
let stringValue = Int(Mvalue!)
use like below
if let stringValue = Int(Mvalue) {
//Now it prints your perfect unwrapping value
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}

UILabel variable needs to be an Optional Double but I don't want the the label to display optional(valueOfNumber)

I'm trying to complete the CS193P Course independently. I am on assignment 2 of the course and part of the assignment asks for me to do the following:
"Change the computed instance variable displayValue to be an Optional Double rather than a Double"
I was able to change displayValue to be an Optional Double, but now my UILabel which shows the displayValue now will display the optional value instead of the double value (which makes sense).
Example:
5 (then press enter) will display a value of Optional(5.0) in the UILabel.
Here is what I tried:
I determined that result and displayValue! will return a double.
I tried changing display.text = result to display!.text! = result but that did not fix the issue.
Here is a snippet of my code, I think you shouldn't need any more but please comment if you think I should show something else!
P.S. the name of the display is display
#IBAction func enter() {
if let result = brain.pushOperand(displayValue!) {
displayValue = result
} else {
displayValue = 0
}
}
var displayValue: Double? {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display!.text! = "\(newValue)" //display is the UILabel
}
I believe the display is supposed to be blank when, for example, the stack cannot be evaluated to give a result.
So you can just use
var displayValue: Double? {
get { return NSNumberFormatter().numberFromString(display.text!)?.doubleValue }
set { if newValue != nil { display.text = "\(newValue!)" }
else { display.text = " " }
}
}
And then for "enter"
#IBAction func enter() {
if let dV = displayValue {
brain.pushOperand(dV)
displayValue = brain.evaluate()
}
userIsInTheMiddleOfTypingANumber = false
}
This solution worked for me. I am working through this course independently too. It is tricky and I have to listen to the lectures LOTS of times :-)
Jacki

Calling/messaging code crashing?

I have buttons that when pressed, will call/message a number from an array. i.e. button1 will call the number at index 0 of the array, button2 at index 1, etc.. For some reason whenever the number from the array contains a format other than xxx-xxx-xxx it crashes (i.e. (xxx) xxx-xxx). And yet, the log gives me the following error even though the array isn't nil:
Anyone know why this is happening?
Here is the code for everything:
import UIKit
import AddressBook
var contactInfo: [String] = []
[...]
override func viewDidLoad() {
super.viewDidLoad()
//this is the function that grabs the array from an app group
setUpCallMessageButtons()
[...]
callButton1.addTarget(self, action: "call:", forControlEvents: UIControlEvents.TouchUpInside)
}
func call(sender:UIButton!)
{
if (sender == callButton1) {
println("\(contactInfo)")
var url:NSURL? = NSURL(string: "tel:\(contactInfo[0])")
self.extensionContext?.openURL(url!, completionHandler:{(success: Bool) -> Void in
})
}
}
func setUpCallMessageButtons(){
let appGroupID = "**redacted**"
let defaults = NSUserDefaults(suiteName: appGroupID)
contactInfo = (defaults!.objectForKey("contactInfo") as! [String])
println("\(contactInfo)")
//This is gives the log down below. As you can see, none are nil.
}
Buttons 1,2 and 5 work while 3 and 4 always crash.
My guess is that if the phone number isn't formatted correctly, the call to convert it to an NSURL is failing and returning nil.
You probably need to wrap your call to openURL in an optional binding ("if let") block:
var url:NSURL? = NSURL(string: "tel:\(contactInfo[0])")
if let url = url
{
self.extensionContext?.openURL(url!,
completionHandler:
{
(success: Bool) -> Void in
}
}
else
{
println("Phone number \(contactInfo[0]) is not in a valid format")
}
You might want to strip away parenthesis from your phone number before trying to create your URL. A simple way would be to use the NSString method stringByReplacingOccurrencesOfString:withString:.
Here's a little storyboard - which shows you where the nil is coming from
Unexpectedly found nil means there is a variable which is expected to be non-nil but at run time was nil
This is the line of code that is causing the issue
self.extensionContext?.openURL(url!, completionHandler:{(success: Bool)
It expects url to be non-nil (i.e. the !) but it is definitely nil (see image)
If this data comes from the user or from the internet, you might want a method to strip away all non-numeric characters. Something like this (from a working playground I just banged out) :
import UIKit
func digitsOnly(#fromString: String) -> String
{
var workString = NSMutableString(string: fromString)
let digitsSet = NSCharacterSet.decimalDigitCharacterSet()
var index: Int
for index = count(fromString)-1; index>=0; index--
{
if !digitsSet.characterIsMember(workString.characterAtIndex(index))
{
workString.deleteCharactersInRange(NSRange(location:index, length:1))
}
}
return workString as String
}
let testString = "(555) 111-2222"
let result = digitsOnly(fromString:testString)
println("digitsOnly(\"\(testString)\") = \"\(result)\" ")
This displays:
digitsOnly("(555) 111-2222") = "5551112222"
Edit:
Or alternately a more Swift-like version of the same function:
func digitsOnly(#fromString: String) -> String
{
var result = String()
let digitsSet = NSCharacterSet.decimalDigitCharacterSet()
for char in fromString
{
if digitsSet.characterIsMember(char as unichar)
result += char
}
}
EDIT #2:
You can increase the set of characters that is left in place by changing the character set you use. Replace the line
let digitsSet = NSCharacterSet.decimalDigitCharacterSet()
With
let digitsSet = NSCharacterSet(charactersInString: "0123456789+-")
To preserve "+" signs and dashes. (Edit the string to include the characters you need.)

Resources