2

I am building an idle clicker app in Swift and I am adding in auto clicks through a function. I want to be able to enter the price through the input for the function, but because the input is a constant, I can't add to the cost price by 9% like I want every time the user clicks the upgrade.

For example if I type 50.0 into the initialPrice how would I make it so that it increases by 10% every time the user clicks it.

func upgrade(intialPrice : Float) {
    var upgradePrice = intialPrice
    AutoClicks += 1
    totalClicks = totalClicks - Int(upgradePrice)
    upgradePrice = upgradePrice + (upgradePrice * 0.1)
    burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}

I am very new to coding so if you see any way I could make this shorter that would be very helpful.

1
  • Please provide information for other variable also. Commented Jan 21, 2019 at 9:44

3 Answers 3

2

The other answers have suggested using an inout parameter, and while this will work, it is not a pattern I would recommend. Generally it is better to avoid "side effects" in functions and use inout only when there is a very good reason.

The more general approach would be to have a function that returns the new value.

You might also want to consider using a Decimal rather than a Float when dealing with currency.

Similarly, updating the label probably shouldn't be in this function

func upgrade(initialPrice : Decimal) -> Decimal {
    autoClicks += 1
    totalClicks -= Int(truncating: initialPrice as NSDecimalNumber)
    return initialPrice * 1.1
}

You can then call this function like so:

price = upgrade(initialPrice: price)
burritoLvl1Label.text = ("$" + "\(Int(truncating:price as NSDecimal))")
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the response, I just have a few questions. Firstly, why wouldn't you update the label text in the function because when I update it outside using the "$(Int(initialPrice))", Xcode tells me that I have used an unresolved identifier and secondly, if I try to update the label in the function, Xcode tells me "Cannot invoke initializer for type 'Int' with an argument list of type '(Decimal)'". Finally, when I call the function e.g. upgrade(initialPrice: 50.0 ), Xcode tells me that "Result of call to 'upgrade(initialPrice:)' is unused". Sorry these questions might seem very dumb.
Also what are the differences of using Decimals over Floats, and what does (truncating: initialPrice as NSDecimalNumber) mean.
I have updated my answer to show how you would call the function. The reason for not updating the text field in the function is that you normally try and separate functions of your app; have one place where you update the field rather than having updates all over. Floats are an approximation of a decimal number; you might store "1.3" in a Float and that may be approximated as "1.299999999999". Over enough calculations these errors can accumulate. A Decimal exactly stores base-10 decimal numbers. truncating basically throws away the decimal portion in order to get an Int
Int doesn't have an initialiser that takes a Decimal directly, so you have to cast it to a NSDecimalNumber in order to satisfy the requirements of the Int(truncating:) initialiser
Sorry to be painful. But when I type price = upgrade(initialPrice: price ) it says price is an unresolved identifier. Also when I type burritoLvl1Label.text = ("$" + "\(Int(truncating:upgradePrice as NSDecimal))") It also says that upgradePrice is an unresolved identifier.
|
2

You need to pass the value in as an inout argument to be able to mutate it. You can also make your implementation more concise by using the compound assignment operators, +=, -= and *=. You should also make sure that you conform to the Swift naming convention, which is loweCamelCase for function and variable names (autoClicks) and UpperCamelCase for types.

func upgrade(initialPrice: inout Float) {
    autoClicks += 1
    totalClicks -= Int(upgradePrice)
    upgradePrice *= 1.1
    burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}

However, you should be aware that in most cases you should return the mutated value from a function instead of mutating it by passing it in as an inout parameter. It is especially bad practice to mutate some instance variables of your class without passing them into the function explicitly, while modifying some others using an inout argument.

Comments

1

You should make your input parameter as inout.

More info about swift functions.

func upgrade(intialPrice: inout Float) {
    var upgradePrice = intialPrice
    AutoClicks += 1
    totalClicks = totalClicks - Int(upgradePrice)
    upgradePrice = upgradePrice + (upgradePrice * 0.1)
    burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}

Hope it helps!

1 Comment

The "best" is effectively to have a func returning value. func upgrade(intialPrice : Float) -> Float { } ; in the func, you add return upgradePrice ; and you call the function as thePrice = upgrade(intialPrice: thePrice)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.