Sallu
Sallu

Reputation: 489

Unwrapping Optional String To Int & Making it non-optional

It has been a long time since I have coded in iOS and I am upgrading the old app to swift 3. I am really struggling with one issue of using optional variables.

I have a textfield which is optional. I want it unwrapped into a non-optional Int so that I can use it in the other functions for calculation.

@IBOutlet weak var txtRuns: UITextField!

func sendScore()
{   
    let runs        = txtRuns.text!
    let overs       = txtOvers.text!
    let balls       = txtBalls.text!
    let wkts        = txtWkts.text!
    let target      = txtTarget.text!
    let totalOvers  = txtTotalOvers.text!

    let strData  = "S|R\(runs)" + getOptionalScoreData(
             runs: Int(runs),
             wkts: Int(wkts),
             overs: Int(overs),
             balls: Int(balls),
             target: Int(target),
             totalOvers: Int(totalOvers)
             )
}

func getOptionalScoreData(runs: Int, wkts: Int, overs: Int, balls: Int, target: Int, totalOvers: Int) -> String
{
    if ( runs == 0 ) {
        return  getCurrentRunRate(runs: runs)
    }

    return "";
}

As you can see, I have so many functions to call and I want this textfield to turn into non-optional INT.

Now I have tried several options that I read over here but the error messages only change. The problem didn't solve.

Current ERROR is

 The value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?

Please help. Thanks

.................

Please note that I don't think nested check is a nice idea here because all these variables are independent of each other. One can be nil but other can be still passed and used.

If I nest checks like this, it means that no other value will be passed if runs are nil.

if let runs = txtRuns.text, let runsInInt = Int(runs) {
    if let overs = txtOvers.text, let oversInInt = Int(overs) {
        if let wkts = txtWkts.text, let wktsInInt = Int(wkts) {

            strData = "S|R\(runs)\(overs)\(wkts)" + getOptionalScoreData( runs: runsInInt, overs: oversInInt, wkts: wktsInInt)

}

Upvotes: 1

Views: 576

Answers (2)

adev
adev

Reputation: 2092

If you are frequently getting value from UITextField as Int, you can add an extension as follows:

extension UITextField {
    var intValue: Int {
        get {
            if let text = self.text {
                return Int(text) ?? 0
            }
            return 0
        }
        set {
            self.text = String(newValue)
        }
    }
}

You can add the above as private extension in your viewcontroller too. Now you can rewrite your code as:

func sendScore() {
    let strData  = "S|R\(txtRuns.intValue)\(overs.intValue)\(wkts.intValue)" + getOptionalScoreData(
        runs: txtRuns.intValue,
        wkts: wkts.intValue,
        overs: overs.intValue,
        balls: balls.intValue,
        target: target.intValue,
        totalOvers: totalOvers.intValue)
    )
}

Upvotes: 4

Codus
Codus

Reputation: 1473

Int(runs) call constructor of Int following:

public init?(_ text: String, radix: Int = default)

Because String to Int might failed due to the String might not a valid integer.

How would you deal with it?

You can reference Sallu's comment.

  1. user ! to guarantee the String in UITextField is absolute a valid integer, or app crash.

runs: Int(runs)!

  1. user ?? to give a default value if the String in UITextField is not a valid integer.

runs: Int(runs) ?? 0

In the case the default value is 0

Upvotes: 0

Related Questions