Skip to content

How to use Ternary Operators in SwiftUI | SwiftUI Bootcamp #24

You want a button to turn red when selected and blue when not — but you don't want to write an if-else block just to pick a color. The ternary operator lets you express this kind of two-option logic inline inside a modifier, keeping your layout code compact and readable.

What You'll Learn

  • How to write and read the ternary operator condition ? valueIfTrue : valueIfFalse
  • How to embed ternary expressions directly inside SwiftUI modifiers like .fill(), .frame(), and .cornerRadius()
  • When the ternary operator is the right tool versus when a full if-else block is cleaner

Mental Model

The ternary operator is a question with exactly two possible answers. Read it out loud: "Is isStartingState true? If yes, use this value. If no, use that value." The structure condition ? A : B maps directly onto that sentence.

Think of it like a light switch wired to two different lights. The switch (your Boolean) can only be in one position at a time, so exactly one light is always on. The ternary is the wiring diagram — it defines which light turns on for each switch position. You can wire the same switch to control the color, the size, and the shape simultaneously, as this lesson demonstrates.

Detailed Explanation

In Swift, the ternary operator condition ? trueValue : falseValue is an expression, not a statement. That distinction matters in SwiftUI: modifier arguments expect expressions, not statements. You cannot write if/else inside .frame(width: ...), but you can write a ternary. This makes ternary operators the natural fit for modifier parameters that depend on state.

Every place in SwiftUI where you pass a value — a color to .fill(), a number to .frame(), an angle to .rotationEffect() — the ternary works without extra syntax. The same Boolean flag can drive multiple modifiers simultaneously, and each modifier evaluates the ternary independently. This is how you produce coordinated multi-property animations: change one flag and all the ternaries that reference it evaluate their new branch, creating a compound visual change.

The ternary is best when you're choosing between exactly two values of the same type. Once your condition involves three or more outcomes, or when the true/false values are complex, an if-else inside a body (or a computed property that returns the value) is easier to read. A nested ternary like a ? b : c ? d : e is almost always a mistake — it reads poorly and is difficult to maintain.

Code Structure

TernaryBootcamp.swift uses a single @State var isStartingState: Bool to drive four separate ternary expressions across text content, corner radius, fill color, and frame dimensions. Toggling the button simultaneously changes all four, demonstrating how one Boolean can coordinate multiple visual properties.

Complete Code

TernaryBootcamp.swift

swift
import SwiftUI

struct TernaryBootcamp: View {
    
    @State var isStartingState: Bool = false // single source of truth for all four ternaries below
    
    var body: some View {
        VStack {
            Button("Button: \(isStartingState.description)") {
                isStartingState.toggle() // one state change triggers re-evaluation of all ternaries
            }
            
            Text(isStartingState ? "STARTING STATE!!!" : "ENDING STATE.") // ternary inside a View initializer

            RoundedRectangle(cornerRadius: isStartingState ? 25 : 0) // rounded when true, sharp corners when false
                .fill(isStartingState ? Color.red : Color.blue)        // color switches with the same flag
                .frame(
                    width: isStartingState ? 200 : 50,   // wide when true, narrow when false
                    height: isStartingState ? 400 : 50)  // tall when true, square-ish when false
            
            Spacer()
        }
    }
}

struct TernaryBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        TernaryBootcamp()
    }
}

Code Walkthrough

  1. @State var isStartingState: Bool = false — The single boolean that the entire view's conditional display is derived from. Notice how this single variable controls four separate visual properties simultaneously.

  2. isStartingState.toggle() in the button action — Flips the flag. SwiftUI re-evaluates body, every ternary expression sees the new value, and the view updates. The button label also updates because its title string contains a ternary.

  3. Text(isStartingState ? "STARTING STATE!!!" : "ENDING STATE.") — The ternary is inside the Text initializer. When the Bool changes, this view gets a new string value. Because the Text content changed, SwiftUI re-renders the Text.

  4. RoundedRectangle(cornerRadius: isStartingState ? 25 : 0) — The corner radius is passed directly to the initializer as a ternary result. This swaps between a fully rounded shape and a sharp rectangle.

  5. .fill(isStartingState ? Color.red : Color.blue) — A modifier whose argument is a ternary. This is idiomatic SwiftUI — you'll use this pattern constantly for colors, fonts, and opacity.

  6. .frame(width: isStartingState ? 200 : 50, height: isStartingState ? 400 : 50) — Both width and height use the same flag. The shape dramatically changes size when toggled. If this change is wrapped in withAnimation, SwiftUI will interpolate between the two sizes smoothly (covered in later lessons).

Common Mistakes

Mistake: Using the ternary to choose between two completely different view types
condition ? Text("Hi") : Image(systemName: "star") produces a compiler error because both branches must return the same type. Use if-else when you need different view types in different states.

Mistake: Nesting ternaries for three-state logic
a ? x : b ? y : z works syntactically but is very hard to read. A switch statement or a computed property returning the appropriate value is far clearer.

Mistake: Forgetting that a ternary inside a modifier is NOT animated by default
The values swap instantly when state changes. To animate the transition between the two values, wrap the state mutation in withAnimation { isStartingState.toggle() } (covered in lesson 25).

Key Takeaways

  • The ternary condition ? A : B is an expression, making it usable anywhere a value is expected — including inside modifier arguments.
  • One Boolean flag can drive multiple ternary expressions simultaneously, producing coordinated visual changes across several modifiers.
  • Use ternary for simple two-option choices on a single line; use if-else blocks when branches are complex or involve different view types.

Last updated: June 27, 2026

Released under the MIT License.