{"id":"l-sw-2-2","courseId":"swift-essentials","lang":"en","kind":"lesson","summary":"Replace fragile strings with enums, attach data to each case with associated values, and let exhaustive switches find every place a new case needs handling.","html":"<p>In the last section, an expense’s category was a <code dir=\"ltr\">String</code>. That works until someone writes <code dir=\"ltr\">&quot;Fod&quot;</code>, or <code dir=\"ltr\">&quot;food&quot;</code> in one place and <code dir=\"ltr\">&quot;Food&quot;</code> in another, and the monthly total silently misses half your groceries. Nothing in the type said which strings were valid. An <strong>enum</strong> says exactly that: here is the complete list of possible values, and nothing else is allowed.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">Enums with raw values</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Category.swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">enum</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">CaseIterable </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> food</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> transport</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> housing</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> fun</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> title: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        rawValue.capitalized</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> symbolName: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        switch</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> self</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .food</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"fork.knife\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .transport</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"bus\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .housing</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"house\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .fun</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"ticket\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p><code dir=\"ltr\">Category</code> now has exactly four values. Write <code dir=\"ltr\">.fod</code> and the build fails. The <code dir=\"ltr\">: String</code> gives each case a <strong>raw value</strong>, its name as a string by default (<code dir=\"ltr\">Category.food.rawValue</code> is <code dir=\"ltr\">&quot;food&quot;</code>), which is what you’ll save to disk and read from JSON later. Going the other way is failable, because not every string is a category: <code dir=\"ltr\">Category(rawValue: &quot;fun&quot;)</code> is <code dir=\"ltr\">.fun</code>, and <code dir=\"ltr\">Category(rawValue: &quot;Fun&quot;)</code> is <code dir=\"ltr\">nil</code>.</p>\n<p><code dir=\"ltr\">CaseIterable</code> asks the compiler to generate <code dir=\"ltr\">Category.allCases</code>, an array of every case in declaration order. Pocket Budget’s category picker will loop over it, so adding a case adds a row to the picker for free.</p>\n<p>Enums can have computed properties and methods, just like structs. <code dir=\"ltr\">symbolName</code> maps each case to an SF Symbols icon name, and the <code dir=\"ltr\">switch</code> inside it has no <code dir=\"ltr\">default</code>.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Exhaustive switches are a feature</h2>\n<p>Suppose you add <code dir=\"ltr\">case gifts</code> next month. The build immediately fails at <code dir=\"ltr\">symbolName</code> with “switch must be exhaustive”, and at every other <code dir=\"ltr\">switch</code> over <code dir=\"ltr\">Category</code> in the project. The compiler has produced your to-do list. Compare that with the string version, where a new category quietly falls into whatever <code dir=\"ltr\">default</code> branch existed and shows the wrong icon in production.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Adding default to an enum switch</span></p>\n<p><code dir=\"ltr\">default: &quot;questionmark&quot;</code> makes today’s error go away and tomorrow’s bug invisible. When you add <code dir=\"ltr\">.gifts</code>, nothing tells you that this switch never learned about it. Over an enum you own, list every case explicitly and let the compiler keep you honest.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">Associated values: cases that carry data</h2>\n<p>Raw values are fixed per case. Some data varies per instance. Pocket Budget records how an expense was paid, and each method needs different details:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">PaymentMethod.swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">enum</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> PaymentMethod</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> cash</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(lastFour: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> transfer</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(bank: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, reference: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> lunch: PaymentMethod </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .cash</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> groceries: PaymentMethod </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">lastFour</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"4242\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> rent: PaymentMethod </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">transfer</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">bank</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Monzo\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">reference</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"RENT-10\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span></code></pre></div>\n<p>Each case has its own shape. A cash payment carries nothing, a card payment carries four digits, and a transfer carries a bank and an optional reference. A struct would need three optional properties and a comment explaining which ones are filled in when. The enum makes invalid combinations, such as a cash payment with a bank name, impossible to construct.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 210\" role=\"img\" aria-labelledby=\"l-sw-2-2-t1\"><defs><marker id=\"arrow-l-sw-2-2-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-sw-2-2-t1\">The PaymentMethod enum branches into three cases: cash with no data, card carrying lastFour, and transfer carrying bank and an optional reference.</title>\n  <rect class=\"d-box-primary\" x=\"250\" y=\"15\" width=\"180\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"340\" y=\"46\" text-anchor=\"middle\">PaymentMethod</text>\n  <path class=\"d-arrow\" d=\"M300 65 L120 115\" marker-end=\"url(#arrow-l-sw-2-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M340 65 L340 115\" marker-end=\"url(#arrow-l-sw-2-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M380 65 L560 115\" marker-end=\"url(#arrow-l-sw-2-2-1)\"/>\n  <rect class=\"d-box\" x=\"40\" y=\"120\" width=\"160\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"120\" y=\"150\" text-anchor=\"middle\">.cash</text>\n  <text class=\"d-label-muted\" x=\"120\" y=\"172\" text-anchor=\"middle\">no data</text>\n  <rect class=\"d-box-accent\" x=\"260\" y=\"120\" width=\"160\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"340\" y=\"150\" text-anchor=\"middle\">.card</text>\n  <text class=\"d-label-muted\" x=\"340\" y=\"172\" text-anchor=\"middle\">lastFour</text>\n  <rect class=\"d-box-success\" x=\"480\" y=\"120\" width=\"180\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"570\" y=\"150\" text-anchor=\"middle\">.transfer</text>\n  <text class=\"d-label-muted\" x=\"570\" y=\"172\" text-anchor=\"middle\">bank, reference?</text>\n</svg><figcaption>One enum, three differently shaped cases</figcaption></figure>\n<h2 id=\"sec-4\" tabindex=\"-1\">Getting the data back out</h2>\n<p>You read associated values with pattern matching in a <code dir=\"ltr\">switch</code>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> label</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> method: PaymentMethod) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    switch</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> method {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .cash</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Cash\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> lastFour)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Card ending </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">lastFour</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">transfer</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> bank, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> reference</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">bank</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> transfer, ref </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">reference</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">transfer</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> bank, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">nil</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">bank</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> transfer\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">label</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: groceries)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// \"Card ending 4242\"</span></span></code></pre></div>\n<p><code dir=\"ltr\">let lastFour</code> binds the associated value to a new constant for that case. The two <code dir=\"ltr\">.transfer</code> cases show how far patterns go: <code dir=\"ltr\">let reference?</code> matches only when the optional reference has a value and unwraps it, and <code dir=\"ltr\">nil</code> matches when it doesn’t. The compiler still checks that, between them, every possibility is covered.</p>\n<p>When you care about a single case, <code dir=\"ltr\">if case</code> is shorter than a full switch:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">if</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> case</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> .</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> lastFour) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> groceries {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Remind me to check card </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">lastFour</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<aside class=\"callout callout-note\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">Note</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>You’ve used an enum since lesson 2</span></p>\n<p><code dir=\"ltr\">Optional</code> is an enum with two cases, <code dir=\"ltr\">.some(Wrapped)</code> and <code dir=\"ltr\">.none</code>, and <code dir=\"ltr\">nil</code> is shorthand for <code dir=\"ltr\">.none</code>. Every <code dir=\"ltr\">if let</code> you’ve written is pattern matching on an enum with an associated value.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">Enums instead of boolean soup</h2>\n<p>Enums are the right tool whenever a value is “exactly one of these”. A classic example is loading data. The first draft usually looks like three separate properties: <code dir=\"ltr\">isLoading</code>, <code dir=\"ltr\">rates</code>, and <code dir=\"ltr\">errorMessage</code>. Nothing stops all three from being set at once, so every screen has to guess which one wins. One enum removes the guessing:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">enum</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> LoadState</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> idle</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> loading</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> loaded</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">([</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: Decimal])</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    case</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> failed</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>Now the rates exist only in the <code dir=\"ltr\">.loaded</code> case and the message only in <code dir=\"ltr\">.failed</code>, and a <code dir=\"ltr\">switch</code> in the view handles each state once. You’ll build exactly this when Pocket Budget starts fetching exchange rates. Reach for an enum whenever you catch yourself comparing strings or juggling booleans that should never be true together.</p>\n<p>Your types can now describe Pocket Budget’s data precisely. Next you’ll give them shared abilities with protocols, such as “can be compared” or “has a stable id”, and add behaviour to existing types with extensions.</p>\n","toc":[{"id":"sec-1","text":"Enums with raw values","level":2},{"id":"sec-2","text":"Exhaustive switches are a feature","level":2},{"id":"sec-3","text":"Associated values: cases that carry data","level":2},{"id":"sec-4","text":"Getting the data back out","level":2},{"id":"sec-5","text":"Enums instead of boolean soup","level":2}],"takeaways":["An enum lists every valid value of a type, so a typo like “Fod” becomes a compile error instead of a silent bug.","[object Object]","Associated values attach different data to different cases, such as the last four digits for <code dir=\"ltr\">.card</code>.","Switch over enums without <code dir=\"ltr\">default</code>, so adding a case makes the compiler list every switch you must update."],"further":[{"title":"Enumerations","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations/"},{"title":"CaseIterable","url":"https://developer.apple.com/documentation/swift/caseiterable"}],"quiz":[{"q":"<p><code dir=\"ltr\">enum Category: String { case food, transport }</code>. What does <code dir=\"ltr\">Category(rawValue: &quot;Food&quot;)</code> return?</p>","options":[{"text":"<code dir=\"ltr\">.food</code>, because raw-value matching ignores case.","why":"Raw-value matching is exact. The raw value of <code dir=\"ltr\">food</code> is “food”, lowercase."},{"text":"A crash, because “Food” isn’t a valid raw value.","why":"The failable initializer exists precisely to avoid crashing on bad input."},{"text":"<code dir=\"ltr\">nil</code>","why":"Correct. <code dir=\"ltr\">init(rawValue:)</code> is failable and returns <code dir=\"ltr\">Category?</code>; “Food” doesn’t match “food”."}],"answer":2},{"q":"<p>You add <code dir=\"ltr\">case gifts</code> to <code dir=\"ltr\">Category</code>. Every <code dir=\"ltr\">switch</code> over <code dir=\"ltr\">Category</code> uses explicit cases and no <code dir=\"ltr\">default</code>. What happens on the next build?</p>","options":[{"text":"The compiler reports each switch that doesn’t handle <code dir=\"ltr\">.gifts</code>.","why":"Correct. Exhaustiveness checking turns “find every place that needs updating” into a list of errors."},{"text":"The build succeeds, and <code dir=\"ltr\">.gifts</code> falls into the last case at runtime.","why":"Swift never routes an unhandled case anywhere silently."},{"text":"The build succeeds, and the app crashes when it meets <code dir=\"ltr\">.gifts</code>.","why":"Without a <code dir=\"ltr\">default</code>, the gap is caught at compile time, not at runtime."}],"answer":0},{"q":"<p>Which declaration models “paid by card, and we know the last four digits”?</p>","options":[{"text":"<code dir=\"ltr\">case card = &quot;4242&quot;</code>","why":"A raw value is fixed for the case; every card payment would end in 4242."},{"text":"<code dir=\"ltr\">case card(lastFour: String)</code>","why":"Correct. An associated value is stored per instance, so each payment carries its own digits."},{"text":"<code dir=\"ltr\">case card; var lastFour: String</code>","why":"Enums can’t have stored instance properties; associated values are how cases carry data."},{"text":"<code dir=\"ltr\">case card(String) = &quot;card&quot;</code>","why":"Swift doesn’t allow raw values on an enum whose cases have associated values."}],"answer":1}],"exercise":{"kind":"fill","language":"swift","template":"enum Category: String, {{0}} {\n    case food, transport, fun\n}\nprint(Category.{{1}}.count)   // 3\n\nenum PaymentMethod {\n    case cash\n    case card(lastFour: String)\n}\n\nfunc label(for method: PaymentMethod) -> String {\n    switch method {\n    case .cash:\n        return \"Cash\"\n    case .card({{2}} lastFour):\n        return \"Card ending \\(lastFour)\"\n    }\n}","blanks":[{"answers":["CaseIterable"]},{"answers":["allCases"]},{"answers":["let"]}],"title":"Model categories and payment methods","prompt":"<p>Complete Pocket Budget’s two enums. <code dir=\"ltr\">Category</code> must provide a list of all its cases so the picker can show them, and <code dir=\"ltr\">label(for:)</code> must read the last four digits out of a card payment.</p>\n","hints":["The protocol that generates a list of every case has “Case” in its name.","The generated list is a static property: <code dir=\"ltr\">Category.____</code>.","Inside a <code dir=\"ltr\">case</code> pattern, the keyword that binds an associated value to a new constant is the same one you use to declare constants."],"explanation":"<p><code dir=\"ltr\">CaseIterable</code> makes the compiler generate <code dir=\"ltr\">Category.allCases</code>, an array of every case in declaration order, so <code dir=\"ltr\">count</code> is 3. In the switch, <code dir=\"ltr\">case .card(let lastFour)</code> matches card payments and binds the associated value to the constant <code dir=\"ltr\">lastFour</code> for that branch.</p>\n<p>Notice the switch has no <code dir=\"ltr\">default</code>. If you add <code dir=\"ltr\">case transfer(bank: String)</code> later, this function stops compiling until you handle it, which is exactly what you want.</p>\n","checkLabels":{}},"words":685,"readMinutes":3}