Running operations on numbers with commas in Swift3 - swift

If I have a number that is over 1,000, so that it has a comma in it, how can I either strip out the commas, or convert this number into a Double, so that I can run mathematical operations on it?
Right now, I have the following code:
let oldBFTally: Double = Double(plBFTally.text!)!
let newBFTally: Double = round(1000 * (rawValue + oldBFTally) / 1000)
This code works great, as long as the number is under 1000. But, being that I am formatting the number as text, so that it has commas (ie: 1,234.56), whenever I try to run that first line, it errors out, saying: "fatal error: unexpectedly found nil while unwrapping an Optional value".
Any ideas what I can do to navigate around this issue?

But, being that I am formatting the number as text, so that it has commas (ie: 1,234.56)
You're trying to tackle the problem in the wrong way. If you're generating this string in the first place, then if you want to perform mathematical operations on the number, you shouldn't be displaying it as a string in the UI, then trying to go backwards from the UI back to a number. That's misusing your presentation layer as your data model.
Instead of trying to go back and forth between the UI, use the original value you generated the string from.

#Jim is correct; your text field should simply contain a textual representation of your internal variable, so you shouldn't need to convert back to a double, but for reference, you can use a NumberFormatter
import Foundation
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
if let number = formattter.number(from:"10,000") {
print(number.doubleValue)
}

Related

How to display an int without commas?

I have a list of Text views that include a year saved as an int. I'm displaying it in an interpolated string:
Text("\($0.property) \($0.year) \($0.etc)")
The problem, it adds a comma to the int, for example it displays 1,944 instead of the year 1944. I'm sure this is a simple fix but i've been unable to figure out how to remove the comma. Thanks!
There is explicit Text(verbatim:) constructor to render string without localization formatting, so a solution for your case is
Text(verbatim: "\($0.property) \($0.year) \($0.etc)")
Use Text(String(yourIntValue)) if you use interpolation you need to cast it as a string directly. If you allow the int to handle it, it shows with a ,.
So to recap.
let yourIntValue = 1234
Text(String(yourIntValue)) // will return `1234`.
Text("\(yourIntValue)") // will return `1,234`.
I use the built-in format parameter. It's useful for formatting well beyond just this one specific usage (no commas).
Text("Disk Cache \(URLCache.shared.currentDiskUsage,
format: .number.grouping(.never))"))

Compare integer with string in NSPredicate

I have in project array of workout programs (code for them are on Objective-C) and in every program I have #property (nullable, nonatomic, copy) NSString *scheduleStr; for program durations. This property stores values such as 1 week, 2 weeks, 3 weeks and etc. I need to filter all values bigger than 6 weeks. I'm trying to apply NSPredicate:
predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 6"))
and after this I'm receiving only programs with length 6-9 weeks, but nothing more than 10 weeks, but for sure I have several programs in database with length equal 12 weeks.
If I'm trying to apply something like this:
predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 10"))
I will receive almost all the programs. How to get all programs with more than selected values?
The problem is that, although you specify integerValue, when using the predicate as part of a fetch, CoreData treats your string as a string. In string terms, 10 weeks is "less than" 6 weeks, so it's excluded from the results.
You should store the number (as an Int) instead of storing the string. Adding the text " weeks" is then something you do for display purposes. If you store the number, rather than the string, then CoreData can do a numerical comparison and your predicate will work as you expect.
If you really don't want to do that, there is one workaround, and one hack. The workaround is to filter the objects in memory rather than as part of a fetch. The integerValue will then be correctly interpreted and the comparison will be numerical.
The hack is to force CoreData to treat your string as though it is a number, by using a numeric function, like abs (assuming you only have a positive number of weeks, taking the absolute value leaves the value unchanged):
predicates.append(NSPredicate(format: "abs:(scheduleStr) >= 6"))
To get the integer part in the string in your case you can look into something like:
Suppose element is your string then
let component = element.components(separatedBy: .letters) // this will give you the non letter values
let integerValues = component.filter({ $0 != "" })
print(integerValues[0]) // As first value in your input string is an integer
This will give you the integer part of the string which can be used to filter the array.

how can you append a number to a double in swift

I am trying to make a calculator app in swift as a practise for my IOS development course. for that app I am trying to append a number to an existing double or integer after the user pressed on a specific button, but I don't know how.
if the user pressed on lets say a 5, then I want that the code should append that 5 to the numbers he pressed before
for instance:
the user has typed the following number:
6797.890
and now he wants to add the 5 to the existing number so that the number would be:
6797.8905
I really don't know how to do this in the code, and I really appreciate it if someone could help me by showing how or giving some resource website's for this problem
thanks a lot!
Benji
I know you mentioned that you are supposed to use an Int or Double, but I would try and use NSDecimalNumber and String if you can. It will give you the precision you want and has a convenient way to turn the string into an NSDecimalNumber, NSDecimalNumber(string: "6797.8905"), as well as back to a string, number.stringValue. You can enteredAmount != NSDecimalNumber.notANumber just in case your user input is incompatible.
You must process the input as a string. If you process it as a double, the trailing zero will be lost and your code will not be able to distinguish between adding "5" to 6797.890 and adding "5" to 6797.89
Only convert from String to Double in one direction (from input to data) after displaying the initial value.

Swift 2/3 String implement of rindexOf method

I know there is an build in method to get the index of substring from the original string by using rangeOfString. But it is used to get the first occurrence of a given substring. However what I need to do is to get the last occurrence of the given substring.
This is something like the rindex in python language
So, my question is, How can I do that in Swift 2.x/3? A code snippet example is appreciated.
You are close. Try the below, adding the optional options parameter and searching the string from the back instead.
let myString = "testingteststring"
let lastSubstringRange = myString.range(of: "test", options: String.CompareOptions.backwards)
'lastSubstringRange' will be the range of the last 'test' substring in 'myString'.
For more info, try looking at Apple Developer: https://developer.apple.com/reference/swift/string/1642786-range

Swift - adding values captured in two textfields

I seem to have a problem with a very simple scenario.
I'm trying to add values captured by two text fields (called T1 and T2) and display their total upon pressing a button (GoButton) on a label (Label1).
I tried wording the syntax in multiple ways and it still doesn't work. I feel that some of the syntax I found on the web didn't work for me. I use Xcode 6.3 on Yosemite.
Screenshot:
Is there a chance that there is something I'm missing with my Xcode to accept swift syntax? Please help.
Dante-
There's still a chance the values could be nil. You've correctly !'ed the TextFields so they unwrap automatically, but the Int conversion is also Optional (the Int still thinks it may get a nil value).
Label1.text = "\(T1.text.toInt()! + T2.text.toInt()!)"
Helpful Hint- If you paste your code in here (rather than a screenshot) it's much easier for folks to copy and paste your code into their IDE and test it out.
For those here smarter than me (everyone) I'm curious why Xcode doesn't complain about a single Int conversion:
Label1.text = "\(T1.text.toInt())" // no complaint from the compiler
Value T1.text.toInt() is an Optional Integer. So you must unwrap it first. So use Label1.text = "\(T1.text.toInt()! + T2.text.toInt()!)"
Good luck
Thats because toInt() returns an optional value. You can cast your String to NSString and extract the integer value without returning an optional.
Label1.text = ((T1.text! as NSString).integerValue + (T2.text! as NSString).integerValue + (T3.text! as NSString).integerValue + (T4.text! as NSString).integerValue).description
Label1.text = "\(T1.text.toInt()! + T2.text.toInt()!)" //T1.text.toInt()
is an optional so you should use ! mark otherwise it will return nil
value