{"id":"l-sw-1-2","courseId":"swift-essentials","lang":"en","kind":"lesson","summary":"Read optional types, unwrap them safely with if let, guard let and ??, and explain why a force unwrap is a crash waiting to happen.","html":"<p>The user taps Add Expense, types “12.50” into the amount field, and taps Save. Your code receives a <code dir=\"ltr\">String</code>. Turning it into a number can fail: the field might be empty, or the user might have typed “twelve”. Many languages hand you a <code dir=\"ltr\">NaN</code>, a zero or an exception for that. Swift hands you an <strong>optional</strong>, and makes you deal with the missing case before the code compiles.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">What an optional is</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><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\">import</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Foundation</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\"> typed </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"12.50\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Decimal</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\">: typed)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// amount is Decimal?, not Decimal</span></span></code></pre></div>\n<p>The question mark in <code dir=\"ltr\">Decimal?</code> means “a <code dir=\"ltr\">Decimal</code>, or nothing”. The “nothing” is spelled <code dir=\"ltr\">nil</code>. Under the hood an optional is an enum with two cases, <code dir=\"ltr\">.some(value)</code> and <code dir=\"ltr\">.none</code>, which is why you can picture it as a box that is either full or empty.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 640 220\" role=\"img\" aria-labelledby=\"l-sw-1-2-t1\"><defs><marker id=\"arrow-l-sw-1-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-1-2-t1\">Decimal(string:) returns a Decimal optional. For \"12.50\" the box holds 12.5; for an empty string the box is empty, which is nil. Unwrapping opens the box.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"80\" width=\"170\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"105\" y=\"113\" text-anchor=\"middle\">Decimal(string:)</text>\n  <path class=\"d-arrow\" d=\"M190 100 L300 50\" marker-end=\"url(#arrow-l-sw-1-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M190 116 L300 170\" marker-end=\"url(#arrow-l-sw-1-2-1)\"/>\n  <rect class=\"d-box-success\" x=\"305\" y=\"20\" width=\"150\" height=\"60\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"380\" y=\"47\" text-anchor=\"middle\">.some(12.5)</text>\n  <text class=\"d-label-muted\" x=\"380\" y=\"68\" text-anchor=\"middle\">\"12.50\"</text>\n  <rect class=\"d-box-warn\" x=\"305\" y=\"140\" width=\"150\" height=\"60\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"380\" y=\"167\" text-anchor=\"middle\">nil</text>\n  <text class=\"d-label-muted\" x=\"380\" y=\"188\" text-anchor=\"middle\">\"\" or \"twelve\"</text>\n  <path class=\"d-arrow\" d=\"M455 50 L540 50\" marker-end=\"url(#arrow-l-sw-1-2-1)\"/>\n  <text class=\"d-label\" x=\"590\" y=\"55\" text-anchor=\"middle\">unwrap</text>\n  <path class=\"d-arrow\" d=\"M455 170 L540 170\" marker-end=\"url(#arrow-l-sw-1-2-1)\"/>\n  <text class=\"d-label\" x=\"590\" y=\"175\" text-anchor=\"middle\">handle</text>\n</svg><figcaption>An optional is a box that is either full or empty</figcaption></figure>\n<p>An optional is not the value inside it. Try <code dir=\"ltr\">amount + 5</code> and the compiler stops you with “value of optional type ‘Decimal?’ must be unwrapped to a value of type ‘Decimal’”. That error is the feature. Every place a value might be missing is marked in the type, and Swift won’t let you forget it.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">if let: use the value in one branch</h2>\n<p><code dir=\"ltr\">if let</code> checks the box and, when it’s full, gives you the value under a new non-optional name:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"1\"><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\"> let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Decimal</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\">: typed) {</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\">\"Adding </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">amount</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 style=\"color:#6E7781;--shiki-dark:#8B949E\">// amount is a Decimal here</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">} </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">else</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</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\">\"That isn't a number\"</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>When the unwrapped name matches an existing optional, Swift 5.7 and later let you drop the right-hand side: <code dir=\"ltr\">if let amount { … }</code>. The new <code dir=\"ltr\">amount</code> exists only inside the braces, which is perfect when the value matters for one small branch.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">guard let: exit early, keep the happy path flat</h2>\n<p>Most of the time, a missing value means “stop here”. <code dir=\"ltr\">guard let</code> says exactly that. Here is the function Pocket Budget uses to validate the amount field:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">AmountParser.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\">import</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Foundation</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> parseAmount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">_</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> text: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Decimal</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:#CF222E;--shiki-dark:#FF7B72\">    let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> trimmed </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> text.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">trimmingCharacters</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: .whitespaces)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    guard</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Decimal</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\">: trimmed), amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> else</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> nil</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount</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\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">parseAmount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"12.50\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Any</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// Optional(12.5)</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:#0550AE;--shiki-dark:#79C0FF\">parseAmount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Any</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)        </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// nil</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:#0550AE;--shiki-dark:#79C0FF\">parseAmount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"-3\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Any</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)      </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// nil</span></span></code></pre></div>\n<p>The <code dir=\"ltr\">else</code> block must leave the current scope with <code dir=\"ltr\">return</code>, <code dir=\"ltr\">throw</code>, <code dir=\"ltr\">break</code> or <code dir=\"ltr\">continue</code>, and the compiler enforces it. In exchange, <code dir=\"ltr\">amount</code> stays available as a plain <code dir=\"ltr\">Decimal</code> for the rest of the function. The comma adds a second condition, so one guard rejects both “not a number” and “zero or negative”. Code written this way reads top to bottom: checks first, real work after, no pyramid of nested <code dir=\"ltr\">if</code>s.</p>\n<aside class=\"callout callout-tip\" 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=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">Tip</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Default to guard</span></p>\n<p>Reach for <code dir=\"ltr\">guard let</code> at the top of functions and <code dir=\"ltr\">if let</code> for short, local branches. If you find yourself three <code dir=\"ltr\">if let</code>s deep, rewrite them as guards.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">?? and optional chaining</h2>\n<p>Sometimes a missing value has an obvious default. The nil-coalescing operator <code dir=\"ltr\">??</code> supplies it:</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\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> note: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> nil</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> label </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> note </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">??</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"No note\"</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">        // \"No note\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> noteLength </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> note</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">count</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ??</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">    // 0</span></span></code></pre></div>\n<p><code dir=\"ltr\">note?.count</code> is <strong>optional chaining</strong>: if <code dir=\"ltr\">note</code> is <code dir=\"ltr\">nil</code>, the whole expression becomes <code dir=\"ltr\">nil</code> instead of crashing, and <code dir=\"ltr\">??</code> turns that into <code dir=\"ltr\">0</code>. Chains can be long (<code dir=\"ltr\">expense?.category?.name</code>), and they stop at the first <code dir=\"ltr\">nil</code>.</p>\n<p>Optionals are also a design decision, not only something functions hand you. In Pocket Budget an expense always has a title and an amount, so those are plain <code dir=\"ltr\">String</code> and <code dir=\"ltr\">Decimal</code>. A note is genuinely optional, so it’s <code dir=\"ltr\">String?</code>. Resist making things optional “to be safe”: every <code dir=\"ltr\">?</code> you add is a question every reader of that value has to answer. Make a property optional only when “no value” is a real, meaningful state.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">The force unwrap</h2>\n<p>There is one more way to open the box: <code dir=\"ltr\">!</code>.</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\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Decimal</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\">: typed)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!</span></span></code></pre></div>\n<p>If <code dir=\"ltr\">typed</code> is “12.50”, this works. If the field is empty, your app dies with “Fatal error: Unexpectedly found nil while unwrapping an Optional value”. There’s no error message for the user and no chance to recover.</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>Force unwrapping user input</span></p>\n<p><code dir=\"ltr\">Decimal(string: field)!</code> passes every test you write with sensible numbers and then crashes for the first user who taps Save on an empty field. Anything that comes from a person, a file or the network can be <code dir=\"ltr\">nil</code>. Use <code dir=\"ltr\">guard let</code> and show a message instead.</p>\n</aside>\n<p><code dir=\"ltr\">!</code> has legitimate uses, such as <code dir=\"ltr\">URL(string: &quot;https://example.com&quot;)!</code> built from a literal you wrote yourself. There, <code dir=\"ltr\">nil</code> would mean a typo in your code, and crashing during development is the fastest way to find it. Be ready to defend every <code dir=\"ltr\">!</code> in code review.</p>\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>A lenient parser</span></p>\n<p><code dir=\"ltr\">Decimal(string:)</code> reads as many leading digits as it can: <code dir=\"ltr\">Decimal(string: &quot;12,50&quot;)</code> gives <code dir=\"ltr\">12</code>, not <code dir=\"ltr\">nil</code>. In <a href=\"/lesson/swift-essentials/l-sw-3-3\">Lists, Navigation and Forms</a> you replace hand parsing with a <code dir=\"ltr\">TextField</code> that understands the user’s locale.</p>\n</aside>\n<p>With optionals in hand you can handle one missing value safely. Next you’ll store many values at once in arrays, dictionaries and sets, and steer through them with loops and <code dir=\"ltr\">switch</code>.</p>\n","toc":[{"id":"sec-1","text":"What an optional is","level":2},{"id":"sec-2","text":"if let: use the value in one branch","level":2},{"id":"sec-3","text":"guard let: exit early, keep the happy path flat","level":2},{"id":"sec-4","text":"?? and optional chaining","level":2},{"id":"sec-5","text":"The force unwrap","level":2}],"takeaways":["An optional such as <code dir=\"ltr\">Decimal?</code> either holds a value or holds <code dir=\"ltr\">nil</code>, and Swift won’t let you use it as a plain value until you unwrap it.","Use <code dir=\"ltr\">guard let</code> to unwrap at the top of a function and exit early, so the rest of the function works with a real value.","Use <code dir=\"ltr\">if let</code> when you only need the value inside one branch, and <code dir=\"ltr\">??</code> when a sensible default exists.","A force unwrap (<code dir=\"ltr\">!</code>) crashes the app the moment the value is <code dir=\"ltr\">nil</code>; treat every <code dir=\"ltr\">!</code> as a claim you must be able to prove."],"further":[{"title":"Optionals (The Basics)","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Optionals"},{"title":"Optional","url":"https://developer.apple.com/documentation/swift/optional"}],"quiz":[{"q":"<p><code dir=\"ltr\">let note: String? = nil</code>. What does <code dir=\"ltr\">note?.count ?? 0</code> evaluate to?</p>","options":[{"text":"<code dir=\"ltr\">nil</code>","why":"Optional chaining does produce <code dir=\"ltr\">nil</code> here, but <code dir=\"ltr\">?? 0</code> then replaces it with the default."},{"text":"<code dir=\"ltr\">0</code>","why":"Correct. <code dir=\"ltr\">note?.count</code> short-circuits to <code dir=\"ltr\">nil</code>, and <code dir=\"ltr\">??</code> supplies <code dir=\"ltr\">0</code>."},{"text":"The program crashes.","why":"Only a force unwrap (<code dir=\"ltr\">!</code>) crashes on <code dir=\"ltr\">nil</code>. <code dir=\"ltr\">?.</code> and <code dir=\"ltr\">??</code> are the safe forms."},{"text":"It doesn’t compile, because you can’t call <code dir=\"ltr\">count</code> on an optional.","why":"You can’t call it directly, but <code dir=\"ltr\">?.</code> is exactly the syntax that makes the call legal."}],"answer":1},{"q":"<p>Inside a function, after <code dir=\"ltr\">guard let amount = parseAmount(text) else { return }</code>, what is true about <code dir=\"ltr\">amount</code> on the next line?</p>","options":[{"text":"It is still a <code dir=\"ltr\">Decimal?</code>, so you need another unwrap.","why":"<code dir=\"ltr\">guard let</code> binds a non-optional value; that’s the whole point of it."},{"text":"It only exists inside the <code dir=\"ltr\">else</code> block.","why":"Inside <code dir=\"ltr\">else</code>, the value is missing, so there is nothing to bind. A <code dir=\"ltr\">guard let</code> binding is available after the guard, for the rest of the scope."},{"text":"It is a non-optional <code dir=\"ltr\">Decimal</code> you can use until the end of the function.","why":"Correct. The <code dir=\"ltr\">else</code> branch must leave the scope, so the compiler knows <code dir=\"ltr\">amount</code> has a value afterwards."}],"answer":2},{"q":"<p>When is a force unwrap like <code dir=\"ltr\">URL(string: &quot;https://example.com&quot;)!</code> reasonable?</p>","options":[{"text":"When the input is a fixed literal you wrote and tested, so <code dir=\"ltr\">nil</code> would be a programmer error.","why":"Correct. A crash here points at a typo in your own code, not at bad user input."},{"text":"Whenever the value comes from the user, because they usually type valid text.","why":"User input is exactly where <code dir=\"ltr\">nil</code> happens. Unwrap it with <code dir=\"ltr\">guard let</code> or <code dir=\"ltr\">if let</code>."},{"text":"Never; <code dir=\"ltr\">!</code> is deprecated in Swift 6.","why":"<code dir=\"ltr\">!</code> is not deprecated. It’s a deliberate tool with a sharp edge."},{"text":"Whenever you want slightly faster code than <code dir=\"ltr\">if let</code>.","why":"There is no meaningful speed difference. The choice is about safety."}],"answer":0},{"q":"<p>Which line compiles when <code dir=\"ltr\">limit</code> is an <code dir=\"ltr\">Int?</code>?</p>","options":[{"text":"<code dir=\"ltr\">let doubled = limit * 2</code>","why":"You can’t do arithmetic on an optional; Swift needs to know what to do when it’s <code dir=\"ltr\">nil</code>."},{"text":"<code dir=\"ltr\">let doubled = (limit ?? 0) * 2</code>","why":"Correct. <code dir=\"ltr\">??</code> turns the <code dir=\"ltr\">Int?</code> into an <code dir=\"ltr\">Int</code>, so the multiplication is well defined."},{"text":"<code dir=\"ltr\">let doubled: Int = limit</code>","why":"An <code dir=\"ltr\">Int?</code> can’t be assigned to an <code dir=\"ltr\">Int</code> without unwrapping it first."}],"answer":1}],"exercise":{"kind":"spot-bug","language":"swift","code":"import Foundation\n\nfunc addExpense(_ amountText: String, to total: Decimal) -> Decimal {\n    let amount = Decimal(string: amountText)!\n    return total + amount\n}\n\nvar total: Decimal = 0\ntotal = addExpense(\"12.50\", to: total)\ntotal = addExpense(\"\", to: total)   // user tapped Save on an empty field\nprint(total)","bugLines":[4],"title":"Find the crash","prompt":"<p>This early version of Pocket Budget’s add-expense logic works in every demo, then crashes for a real user. Select the line that causes the crash.</p>\n","hints":["Run it in your head with the second call: what does <code dir=\"ltr\">Decimal(string: &quot;&quot;)</code> return?","Look for the one character that says “I promise this is never nil”.","The crash message would be “Unexpectedly found nil while unwrapping an Optional value”."],"explanation":"<p>Line 4 force unwraps the result of <code dir=\"ltr\">Decimal(string:)</code>. For an empty string that result is <code dir=\"ltr\">nil</code>, so <code dir=\"ltr\">!</code> crashes the app. Make the function admit it can fail and let the caller decide:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><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\"> addExpense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">_</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amountText: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">to</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> total: Decimal) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Decimal</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:#CF222E;--shiki-dark:#FF7B72\">    guard</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Decimal</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\">: amountText) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">else</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> nil</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>The caller now has to unwrap the result, which is exactly where you show the user “Enter an amount” instead of crashing.</p>\n","checkLabels":{}},"words":731,"readMinutes":3}