UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: BetterRest and how best to skip zero in a Picker?

Forums > 100 Days of SwiftUI

I'm on #2 of the BetterRest wrap up challenge: "Replace the “Number of cups” stepper with a Picker showing the same range of values."

My first thought was a simple if/else, which works. But, it doesn't seem like the swiftUI way.

ForEach(0..<21) {
   if ($0 > 0) {
      Text("\($0) cup")
  } else if ($0 > 1) {
      Text("\($0) cups")
  }
}

So, I've been trying to reduce it to one Text().

This produces a list with 0 cups at the top.

Text(($0 > 0) ? "\($0) cup" : "\($0) cups")

And, this leaves it blank, but still leaves a blank spot at the top.

Text(($0 > 0) ? "\($0) cup" : ($0 > 1) ? "\($0) cups" : "")

Searching on the topic I found other people being led into localization for this: https://www.hackingwithswift.com/forums/swiftui/betterrest-number-of-cups-picker-question/8678

But, that seems pretty far out of the scope of this beginner tutorial. No?

I also tried to just change my ForEach range to 1...20. But, then it started throwing erreors. And, using 1..<21, it began adding wrong. If someone could explain why, maybe that would help.

Edit: This is weird. Now the if/else is NOT working and they're all displayed as cup. What the? I was just looking at all the plurals a few minutes ago.

And, now there's some green bar overlaying part of my code that says something about a breakpoint that I can't get rid of. Sigh

Edit 2: Now it works again with the if/else. Nothing changed so I guess xcode is a little glitchy.

2      

This option is saying "If the selected value is greater than zero, show 'cup' in the Text view. Otherwise, show 'cups' instead." So, it will only show 'cups' in the Text view if the selected number is zero or lower.

Text(($0 > 0) ? "\($0) cup" : "\($0) cups")

So, maybe ($0 > 0) isn't what you want here. How could you make it say, "If the selected value is equal to 1" instead?

2      

Your original attempt

ForEach(0..<21) {
   if ($0 > 0) {
      Text("\($0) cup")
  } else if ($0 > 1) {
      Text("\($0) cups")
  }
}

Would work fine if you only tested the cases where the user selected 0 or 1. But if you try selecting 2, 3, or any number greater than 0, it would still write 'cup' in the Text view. The else if block would never be reached unless the selected value was less than or equal to 0.

2      

@Fly0strich I may have pasted one of those ternerary phrases wrong. I went through several versions.

I don't know what you mean about the if/else. This works ...

Picker(coffeeAmount == 1 ? "1 cup" : "\(coffeeAmount) cups", selection: $coffeeAmount ) {
    ForEach(0..<21) {
        if ($0 > 0) {
            Text("\($0) cup")
        } else if ($0 > 1) {
            Text("\($0) cups")
        }
    }
}

And, so does this...

Picker(coffeeAmount == 1 ? "1 cup" : "\(coffeeAmount) cups", selection: $coffeeAmount ) {
    ForEach(0..<21) {

        if ($0 == 1) {
            Text("\($0) cup")
        } else if ($0 > 1) {
            Text("\($0) cups")
        }
    }
}

It sounds like you're saying there's some difference between these two that matters.

Doesn't the else if ($0 > 1) ignore anything below 2? Does it maybe iterate through everything twice or something, unless we're more specific? Thanks

Also, aren't we supposed to be using some kind of ternary shorthand for these like Paul was teaching? Is it really okay to be doing all this looping and if/else-ing in a view?

2      

In those examples, you are using the label of the picker to display your selected values. (You didn't show that part of your code before)

The label should be used to give the user an idea of what they should be selecting in the Picker, not to display the selected value.

However, you did set up the ternary operator correctly when you used it in the Picker label. So if you are just looking at the label to see if it is working correctly, then it will be.

But, look at the options that are shown when you try to select an option from the picker. Is it showing "cup" and "cups" properly there? If you use the two examples above, you will see that you get different results.

Anyway, you should end up with something like this...

Picker("Daily Coffee Intake", selection: $coffeeAmount) {
    ForEach(0..<21) {
        Text(($0 == 1) ? "\($0) cup" : "\($0) cups"))
    }
}

Alternatively, you could write it like this... (This is what I did in my project)

Picker("Daily Coffee Intake", selection: $coffeeAmount) {
    ForEach(0..<21) {
        Text("\($0) \($0 == 1 ? "cup" : "cups")")
    }
}

But yes, there is most definitely a difference between the two examples you provided above. When you use..

if something {

} else if somethingElse {

}

When the if condition is true, it will execute the if closure, and completely ignore the else if closure. The else if condition is only considered at all when the if condition is false.

3      

When the if condition is true, it will execute the if closure, and completely ignore the else if closure. The else if condition is only considered at all when the if condition is false.

Thanks. That was what I meant by looping twice. I need to get my terminology straight. I really should have shown the whole loop sooner. My apologies.

Man, this floored me. Though I like your version even better @Fly0strich .

Text(($0 == 1) ? "\($0) cup" : "\($0) cups"))

It was right in front of me the whole time! I thought the first thing I tried was that ternary from the label and it didn't work. Been messing with it ever since. Oh man. Thanks

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.