Create Simple Class with multiple calculating function( ) - swift

Trying to run a simple calculation via a function in my class. I simply want to add bill1 + bill2 and print the total amount spent on bills. So (bill1 + bill2 = total). And then print the total amount.
Current error states - "Code after 'return' will never be executed." Now, is my location for my print in the wrong location or did I declare my variables incorrectly? Should I be using vars instead of lets?
What do you recommend for my function in order to calculate and print the result?
class BillsCalculator
{
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
let monthlyBillAmount1: Double = 34.25
let monthlyBillAmount2: Double = 7.99
let calculateTotalsPerMonth: Double = 0.0
//calculateTotalPerMonth ( = monthlyBillAmount_1 + monthlyBillAmount_2 + 3)
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
//totalBillsPerMonth = add(monthlyBillAmount1 + monthlyBillAmount2)
return totalBillsPerMonth(monthlyBillAmount1 + monthlyBillAmount2)
*Error println("You spend \(totalBillsPerMonth)")
}
}

First: "Code after 'return' will never be executed."
Yes it will not, after you call return you exit the function and return to the function that call it, you probably have an warning in XCode warning you about telling you that
Second: "Should I be using vars instead of lets"
If the value changes you MUST use var, if it does not you SHOULD use let.
Some problems I can see in your code:
class BillsCalculator
{
//use _ in the beginning of the name for class variables
//eg. _nameOfBill instead nameOfBill1
//It is not wrong use nameOfBill1 is just not recommended
//if nameOfBill1 change use var
let nameOfBill1: String = "Medical"
//Why is this declare twice
let nameOfBill1: String = "Hulu"
//Those values look like change should be var
var monthlyBillAmount1: Double = 34.25
var monthlyBillAmount2: Double = 7.99
var calculateTotalsPerMonth: Double = 0.0
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
totalBillsPerMonth = add(monthlyBillAmount1 + monthlyBillAmount2)
//print before return
println("You spend \(totalBillsPerMonth)")
return totalBillsPerMonth(monthlyBillAmount1 + monthlyBillAmount2)
}
}

Here you should either print the value of your total bill or return that value. As you just want to print the total bill amount so I would recommend you to just print, not to return anything. You can refer the below code.
class BillsCalculator
{
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
let monthlyBillAmount1: Double = 34.25
let monthlyBillAmount2: Double = 7.99
let calculateTotalsPerMonth: Double = 0.0
//calculateTotalPerMonth ( = monthlyBillAmount_1 + monthlyBillAmount_2 + 3)
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
calculateTotalsPerMonth= add(monthlyBillAmount1 + monthlyBillAmount2)
println("You spend : "+totalBillsPerMonth);
}
}

One tiny error in your code
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
These two variables have the same name, perhaps one should be:
let nameOfBill2: String = "Hulu"
And yes return is always the last line in the function, so any codes after return will never be executed. If you only want to get the total of two bills, you can simply do this:
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double {
//println("You spend \(totalBillsPerMonth)")
return monthlyBillAmount1 + monthlyBillAmount2
}
and call this function with your bill variables, like:
let bill1 = 34.25
let bill2 = 7.99
let totalBill = calculateTotalsPerMonth(bill1, bill2)
println("You spent \(totalBill)")
Swift is a very smart language, and it is type safe. You can remove the type if you want, more like a personal programming style thing.
let bill1: Double = 34.25
let bill1 = 34.25
They both will be type "Double"

As others have said, you need to put your println statement before return since returns ends the execution of the method; thus println will never be run.
However, I would suggest a few changes to your current approach:
// A bill is an object - why not encapsulate it in a struct.
struct Bill {
let name: String
let amount: Double
}
// Using structs is generally preferred, unless you need inheritance and/or
// references to your BillsCalculator objects.
struct BillsCalculator {
let bill1: Bill
let bill2: Bill
// Using a read-only computed property means you don't need to set
// the total to have an initial value of zero.
var totalBilled: Double {
return bill1.amount + bill2.amount
}
}
// Since you're probably going to want to reuse BillsCalculator,
// don't have each bill set already. Instead, use BillsCalculator's
// initialiser and pass in bills.
let bill1 = Bill(name: "Medical", amount: 34.25)
let bill2 = Bill(name: "Hulu", amount: 7.99)
let cal = BillsCalculator(bill1: bill1, bill2: bill2)
print("You've spend \(cal.totalBilled) this month")

Related

Unresolved identifier error in swift function with nested if loop

I'm currently teaching myself Swift coming from a background of Python recently and Visual Basic originally. I would describe myself as competent in those codes but a novice in Swift. I'm trying to write a function that will return a set number of digits from either the start or end of a long integer. My chosen method has been to convert the integer to a string and then use the prefix or suffix command.
Whilst I can get the function to work if it has no flow control and uses either prefix or suffix (first lot of code), when I try to write one function that does both I get an unresolved identifier error on the turnStringToInteger variable (second lot of code). I'm pretty sure this is because the variable lives within the if {} but if I declare it outside of the if loop (hashed out) this also errors. I appreciate this will have a really simple answer but how do I use the return correctly with a nested if loop?
This works...
//Function to Trim Integer (Prefix Only)
func integerTrim(integer:Int, trimLength:Int) -> Int {
var strFromInteger = String(integer)
var trimmedString = strFromInteger.prefix(trimLength)
var intFromString = Int(trimmedString) ?? 0
return intFromString
}
//Declare Input
var inputInt = 12345678910
//Call Function
var result = integerTrim(integer: inputInt, trimLength: 4)
//Print Results
print(inputInt)
print(result)
This doesn't...!
//Function to trim integer prefix or suffix
func integerTrim(integer:Int, type:String, trimLength:Int) -> Int {
var typeID = type
//var turnStringToInteger: Int
if typeID == "P" {
var turnIntegerToString = String(integer)
var trimmedString = turnIntegerToString.prefix(trimLength)
var turnStringToIngeger = Int(trimmedString) ?? 0
}
else if typeID == "S" {
var turnIntegerToString = String(integer)
var trimmedString = turnIntegerToString.suffix(trimLength)
var turnStringToIngeger = Int(trimmedString) ?? 0
}
return turnStringToInteger
}
//Declare Input
var inputInt = 53737363856453
//Call Function
var result = integerTrim(integer: inputInt, type: "P", trimLength: 4)
//Print Results
print(inputInt)
print(result)
As I am self taught I appreciate I may also not be using best practices. I really want to learn to do this properly so if I am going about all of this the wrong way to begin with I would be equally happy to hear other approaches. For example I did consider turning the integer to an array and then creating the trimmed integer from positions within this array. Would this be more elegant?
If you want to access the variable outside of the scope where it is assigned, you need to declare it in the outer scope.
If you do that without assigning it an initial value, you get an error: variable 'turnStringToInteger' used before being initialized. That happens because Swift sees a path in which turnStringToInteger never gets assigned a value (imagine what happens if "X" is passed in for type).
So your real issue is the use of String as the type for type. It would be better to use an enum that expresses exactly what you want:
enum TrimType {
case prefix, suffix
}
func integerTrim(integer: Int, type: TrimType, trimLength: Int) -> Int {
let typeID = type
var turnStringToInteger: Int
switch typeID {
case .prefix:
let turnIntegerToString = String(integer)
let trimmedString = turnIntegerToString.prefix(trimLength)
turnStringToInteger = Int(trimmedString) ?? 0
case .suffix:
let turnIntegerToString = String(integer)
let trimmedString = turnIntegerToString.suffix(trimLength)
turnStringToInteger = Int(trimmedString) ?? 0
}
return turnStringToInteger
}
Now there are only 2 possibilities for type and the switch handles both.
You call it like this:
let result = integerTrim(integer: inputInt, type: .prefix, trimLength: 4)
... after a little refactoring:
func integerTrim(integer: Int, type: TrimType, trimLength: Int) -> Int {
let turnIntegerToString = String(integer)
let trimmedString: Substring
switch type {
case .prefix:
trimmedString = turnIntegerToString.prefix(trimLength)
case .suffix:
trimmedString = turnIntegerToString.suffix(trimLength)
}
return Int(trimmedString) ?? 0
}
There's a few ways to do this. The root of the problem is your turnIntegerToString lifetime is within the braces - and the return is outside the braces.
func integerTrim(integer:Int, type:String, trimLength:Int) -> Int {
var typeID = type
var turnStringToInteger: Int = 0
// If you don't want to assign it to zero (your nil coalesce implies we can) - instead use...
// var turnStringToInteger: Int! // However - this can crash since your if statement does not cover all situations
if typeID == "P" {
var turnIntegerToString = String(integer)
var trimmedString = turnIntegerToString.prefix(trimLength)
turnStringToIngeger = Int(trimmedString) ?? 0
}
else if typeID == "S" {
var turnIntegerToString = String(integer)
var trimmedString = turnIntegerToString.suffix(trimLength)
turnStringToIngeger = Int(trimmedString) ?? 0
}
return turnStringToInteger
}

Swift String to Int Always Returns nil

I am trying to convert a String to an Int. Seems simple enough, but for somer reason it is always returning nil.
I'm just writing a simple extension to convert dollars to cents:
func dollarsToCents() -> Int {
var temp = self;
temp = temp.replacingOccurrences(of: "$", with: "")
temp = temp.replacingOccurrences(of: ",", with: "")
if let number = Int(temp) {
return number*100
}
return 0
}
I have temp set to "$250.89". number is always nil. No matter how I approach converting temp to an Int it is always nil. Anyone know what I'm doing wrong?
Problem is, that string "250.89" (after removing currency symbol) can't be converted to Int because 250.89 isn't integer. So fix your code by converting it to Double
func dollarsToCents() -> Int {
var temp = self
temp.removeAll { "$,".contains($0) }
//temp = temp.replacingOccurrences(of: "[$,]", with: "", options: .regularExpression)
return Int(((Double(temp) ?? 0) * 100).rounded())
}
or if your "number" always have two decimal places
func dollarsToCents() -> Int {
var temp = self
temp.removeAll { !("0"..."9" ~= $0) }
return Int(temp) ?? 0
}
But I think solution is much easier. Your goal should be saving price value as number (Double,...). Then you don't have to convert String to Double and you can just multiply your number. Then when you need to add currency symbol, just convert your value to String and add $ or use NumberFormatter
let price = 250.89
let formattedPrice = "$\(price)" // $250.89
let price = 250.89
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = "USD"
let formattedPrice = formatter.string(from: price as NSNumber)! // $250.89
Just adding this for the bizarre edge-case that I just encountered - be sure there aren't any whitespaces either trailing or leading in your string when converting to Int from String.
Eg.
for date in next_thirty_days {
let date_buffer: String = date.description[8...9]
date_list.append(Int(date_buffer)!)
}
This will fail if the value for date_buffer has a leading or trailing white-space.
Another edge-case is that there's a leading 0 in the string variable, eg. 07.
Hope it helps :)

Parsing units and amounts from text in swift

I was wondering what the best approach would be to separate multiple items from a string in swift. I'm hoping to separate a unit and an amount from a string and then use those values to create an object of my ingredient class.
For example:
var string = "4 cups sugar"
I would need to grab the 4 (amount) and convert it to an int and then grab the unit (cups)
var amount = 4
var unit = "cups"
Another example:
"3 large eggs"
In this case I would want to pull out the 3 (amount) and the unit would be empty.
var amount = 3
var unit = ""
Then I would create my object using the unit and amount values.
I'm still a novice at swift, and more-so with string manipulation so I'm not entirely sure how to approach this, any help in the right direction would be great.
I am working with an ingredient class that is structured as:
class IngredientModel {
var amount = 0
var unit = ""
init(amount : Int, unit : String) {
self.amount = amount
self.unit = unit
}
In SWIFT you can do this early with optionals & generics. I can show you how? with your example..
Your Ingredient class
class IngredientModel {
var amount = 0
var unit = ""
let units = ["cups","spoon"] //Add your required units
init(string: String) {
let array = string.components(separatedBy: " ")
if let _amount = array.ref(0) {
self.amount = Int(_amount) ?? 0
}
if let _unit = array.ref(1),
units.contains(_unit){
self.unit = _unit
}
}
}
An Array Extension to prevent index out of range
extension Array {
func ref(_ i:Int) -> Element? {
return 0 <= i && i < count ? self[i] : nil
}
}
If I'm reading the apple documentation right, you should use the components(separatedBy) function. The parameter should be one space in quotes like so:
let array = yourString.components(separatedBy: " ")

String convert to Int and replace comma to Plus sign

Using Swift, I'm trying to take a list of numbers input in a text view in an app and create a sum of this list by extracting each number for a grade calculator. Also the amount of values put in by the user changes each time. An example is shown below:
String of: 98,99,97,96...
Trying to get: 98+99+97+96...
Please Help!
Thanks
Use components(separatedBy:) to break up the comma-separated string.
Use trimmingCharacters(in:) to remove spaces before and after each element
Use Int() to convert each element into an integer.
Use compactMap (previously called flatMap) to remove any items that couldn't be converted to Int.
Use reduce to sum up the array of Int.
let input = " 98 ,99 , 97, 96 "
let values = input.components(separatedBy: ",").compactMap { Int($0.trimmingCharacters(in: .whitespaces)) }
let sum = values.reduce(0, +)
print(sum) // 390
For Swift 3 and Swift 4.
Simple way: Hard coded. Only useful if you know the exact amount of integers coming up, wanting to get calculated and printed/used further on.
let string98: String = "98"
let string99: String = "99"
let string100: String = "100"
let string101: String = "101"
let int98: Int = Int(string98)!
let int99: Int = Int(string99)!
let int100: Int = Int(string100)!
let int101: Int = Int(string101)!
// optional chaining (if or guard) instead of "!" recommended. therefore option b is better
let finalInt: Int = int98 + int99 + int100 + int101
print(finalInt) // prints Optional(398) (optional)
Fancy way as a function: Generic way. Here you can put as many strings in as you need in the end. You could, for example, gather all the strings first and then use the array to have them calculated.
func getCalculatedIntegerFrom(strings: [String]) -> Int {
var result = Int()
for element in strings {
guard let int = Int(element) else {
break // or return nil
// break instead of return, returns Integer of all
// the values it was able to turn into Integer
// so even if there is a String f.e. "123S", it would
// still return an Integer instead of nil
// if you want to use return, you have to set "-> Int?" as optional
}
result = result + int
}
return result
}
let arrayOfStrings = ["98", "99", "100", "101"]
let result = getCalculatedIntegerFrom(strings: arrayOfStrings)
print(result) // prints 398 (non-optional)
let myString = "556"
let myInt = Int(myString)

Swift 2.1 Binary operator * cannot be applied to two String operands

I have a calculator, but I can´t resolve this code:
#IBAction func calcular(sender: AnyObject) {
resultado.text = String(format: "", Sliderdosis)
let peso = pesoLabel.text
let dosis = dosisLabel.text
let total = (peso * dosis) * 5 / 250
/* in this point, the program write:
Binary operator * cannot be applied to two String operands** */
resultado.text = total
}
Some body help me please?
I´m a beginner, sorry!
The infix binary operator * does not exist for type String. You are attempting to multiply String objects (that are, inherently, not numerical) hence the error.
I'd suggest you make use of Leo Dabus excellent UITextField extension, however, in your case, extending UILabel (assuming pesoLabel and dosisLabel are UILabel instances)
extension UILabel {
var stringValue : String { return text ?? "" }
var integerValue: Int { return Int(stringValue) ?? 0 }
var doubleValue : Double { return Double(stringValue) ?? 0 }
var floatValue : Float { return Float(stringValue) ?? 0 }
}
Add this to the header of your .swift file. Thereafter you can update you button action method according to:
#IBAction func calcular(sender: AnyObject) {
resultado.text = String(format: "", Sliderdosis)
let peso = pesoLabel.doubleValue
let dosis = dosisLabel.doubleValue
let total = (peso * dosis) * 5 / 250
resultado.text = String(total)
}
Finally note that this subject is well-covered here on SO, so there exists existing threads that can help you convert string to numerical values. E.g.
Swift - Converting String to Int
Swift - How to convert String to Double
Also have a look at the Asking section here on SO, it contains lots of valuable information of how to ask, when to ask, and so on.