{"id":2734,"date":"2026-02-05T11:51:56","date_gmt":"2026-02-05T11:51:56","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2734"},"modified":"2026-02-05T11:51:56","modified_gmt":"2026-02-05T11:51:56","slug":"chapter-74-swift-enums-pattern-matching","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-74-swift-enums-pattern-matching\/","title":{"rendered":"Chapter 74: Swift Enums &#038; Pattern Matching"},"content":{"rendered":"<h3 dir=\"auto\">1. Why do we even need enums? (the most important intuition)<\/h3>\n<p dir=\"auto\">In real life we often have <strong>a fixed number of possible states or categories<\/strong>:<\/p>\n<ul dir=\"auto\">\n<li>The weather is either sunny, cloudy, rainy, snowy\u2026<\/li>\n<li>User role is admin, moderator, member, guest\u2026<\/li>\n<li>Payment status is pending, processing, completed, failed\u2026<\/li>\n<li>App screen state is loading, success, error, empty\u2026<\/li>\n<\/ul>\n<p dir=\"auto\">In old languages people usually use:<\/p>\n<ul dir=\"auto\">\n<li>strings (&#8220;admin&#8221;, &#8220;moderator&#8221;)<\/li>\n<li>integers (0 = pending, 1 = completed)<\/li>\n<li>booleans (isAdmin = true\/false)<\/li>\n<\/ul>\n<p dir=\"auto\">All of these are <strong>dangerous<\/strong> because:<\/p>\n<ul dir=\"auto\">\n<li>You can write typos (&#8220;admnin&#8221;)<\/li>\n<li>You can pass wrong numbers (status = 999)<\/li>\n<li>You can mix unrelated states<\/li>\n<li>The compiler cannot help you remember all cases<\/li>\n<\/ul>\n<p dir=\"auto\"><strong>Swift enums<\/strong> solve all of this.<\/p>\n<p dir=\"auto\">An enum says: <strong>\u201cThis value can be one of these exact possibilities \u2014 and nothing else.\u201d<\/strong><\/p>\n<p dir=\"auto\">The compiler <strong>forces<\/strong> you to handle every case (exhaustiveness checking).<\/p>\n<p dir=\"auto\">That is the single most important superpower of Swift enums.<\/p>\n<h3 dir=\"auto\">2. Basic enum \u2014 the simplest form<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum Weather {\r\n    case sunny\r\n    case cloudy\r\n    case rainy\r\n    case snowy\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>let today = Weather.rainy\r\n\r\nswitch today {\r\ncase .sunny:\r\n    print(\"Wear sunglasses \u2600\ufe0f\")\r\ncase .cloudy:\r\n    print(\"Maybe a light jacket \ud83e\udde5\")\r\ncase .rainy:\r\n    print(\"Take umbrella \u2614\")\r\ncase .snowy:\r\n    print(\"Wear warm coat &amp; boots \u2744\ufe0f\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Key points<\/strong>:<\/p>\n<ul dir=\"auto\">\n<li>Cases start with lowercase (convention)<\/li>\n<li>You always write .caseName when using the value<\/li>\n<li>switch must be <strong>exhaustive<\/strong> \u2192 compiler error if you forget a case<\/li>\n<\/ul>\n<h3 dir=\"auto\">3. Enum with associated values (very powerful \u2014 real game changer)<\/h3>\n<p dir=\"auto\">Very often the state needs to <strong>carry extra information<\/strong>.<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum Result {\r\n    case success(message: String, data: [String])\r\n    case failure(errorCode: Int, message: String)\r\n    case loading\r\n    case cancelled\r\n}\r\n\r\nlet apiResult = Result.success(message: \"Loaded\", data: [\"item1\", \"item2\"])\r\n\r\n\/\/ Pattern matching \u2014 this is where it becomes magic\r\nswitch apiResult {\r\ncase .success(let msg, let items):\r\n    print(\"Success: \\(msg)\")\r\n    print(\"Got \\(items.count) items\")\r\n    \r\ncase .failure(let code, let msg):\r\n    print(\"Error \\(code): \\(msg)\")\r\n    \r\ncase .loading:\r\n    print(\"Still loading\u2026\")\r\n    \r\ncase .cancelled:\r\n    print(\"Request was cancelled\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Real-life example<\/strong> \u2014 network \/ API response (extremely common)<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum NetworkResponse {\r\n    case success(statusCode: Int, data: Data)\r\n    case failure(error: Error)\r\n    case unauthorized\r\n    case noInternet\r\n}\r\n\r\nfunc handle(response: NetworkResponse) {\r\n    switch response {\r\n    case .success(let code, let data):\r\n        if code == 200 {\r\n            print(\"Success \u2014 parsing \\(data.count) bytes\")\r\n        } else {\r\n            print(\"Unexpected status: \\(code)\")\r\n        }\r\n        \r\n    case .failure(let error):\r\n        print(\"Network error: \\(error.localizedDescription)\")\r\n        \r\n    case .unauthorized:\r\n        print(\"Please sign in again\")\r\n        showLoginScreen()\r\n        \r\n    case .noInternet:\r\n        print(\"No internet connection \u2014 showing offline mode\")\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">4. Enum with raw values (when you need to map to String \/ Int)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum HTTPStatus: Int {\r\n    case ok = 200\r\n    case created = 201\r\n    case badRequest = 400\r\n    case unauthorized = 401\r\n    case notFound = 404\r\n    case serverError = 500\r\n}\r\n\r\nlet statusCode = 404\r\nif let status = HTTPStatus(rawValue: statusCode) {\r\n    switch status {\r\n    case .notFound:\r\n        print(\"Page not found\")\r\n    case .ok, .created:\r\n        print(\"Success\")\r\n    default:\r\n        print(\"Other status: \\(status.rawValue)\")\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>String raw value<\/strong> (very common for API endpoints, JSON keys)<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum Endpoint: String {\r\n    case users = \"\/api\/v1\/users\"\r\n    case posts = \"\/api\/v1\/posts\"\r\n    case comments = \"\/api\/v1\/comments\"\r\n}\r\n\r\nlet url = baseURL + Endpoint.posts.rawValue<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Pattern Matching \u2014 the real superpower of Swift enums<\/h3>\n<p dir=\"auto\">Pattern matching is what makes enums so powerful. You can <strong>destructure<\/strong> and <strong>extract<\/strong> associated values very elegantly.<\/p>\n<h4 dir=\"auto\">Basic pattern matching in switch<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum PaymentStatus {\r\n    case pending\r\n    case processing(amount: Double)\r\n    case completed(transactionID: String)\r\n    case failed(reason: String)\r\n}\r\n\r\nlet status = PaymentStatus.completed(transactionID: \"TXN-987654\")\r\n\r\nswitch status {\r\ncase .pending:\r\n    print(\"Waiting for payment\u2026\")\r\n    \r\ncase .processing(let amount):\r\n    print(\"Processing payment of \u20b9\\(amount)\")\r\n    \r\ncase .completed(let txID):\r\n    print(\"Payment successful! Transaction: \\(txID)\")\r\n    \r\ncase .failed(let reason):\r\n    print(\"Payment failed: \\(reason)\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Pattern matching in if \/ guard<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>if case let .completed(txID) = status {\r\n    print(\"Transaction ID: \\(txID)\")\r\n}\r\n\r\nguard case let .completed(txID) = status else {\r\n    print(\"Not completed yet\")\r\n    return\r\n}\r\n\r\n\/\/ happy path \u2014 txID is unwrapped\r\nprint(\"Success \u2014 TX: \\(txID)\")<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Very powerful real pattern<\/strong> \u2014 unwrap + check at once<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>if case let .success(data) = apiResult, data.count &gt; 0 {\r\n    process(data)\r\n} else {\r\n    print(\"No data or failed\")\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">6. Very Common Real-Life Examples You Will Write<\/h3>\n<h4 dir=\"auto\">Example 1 \u2013 API response handling (probably the #1 enum use-case)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum APIResult&lt;T&gt; {\r\n    case success(T)\r\n    case failure(Error)\r\n    case loading\r\n}\r\n\r\nfunc loadUsers(completion: @escaping (APIResult&lt;[User]&gt;) -&gt; Void) {\r\n    \/\/ pretend network call\r\n    DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {\r\n        if Bool.random() {\r\n            completion(.success([User(name: \"Rahul\"), User(name: \"Priya\")]))\r\n        } else {\r\n            completion(.failure(NSError(domain: \"Network\", code: -1009)))\r\n        }\r\n    }\r\n}\r\n\r\nloadUsers { result in\r\n    switch result {\r\n    case .success(let users):\r\n        print(\"Loaded \\(users.count) users\")\r\n        \r\n    case .failure(let error):\r\n        print(\"Failed: \\(error.localizedDescription)\")\r\n        \r\n    case .loading:\r\n        print(\"Still loading\u2026\")\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h4 dir=\"auto\">Example 2 \u2013 Navigation \/ app state (very common in SwiftUI\/UIKit)<\/h4>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Swift<\/div>\n<div>\n<pre tabindex=\"0\"><code>enum ScreenState {\r\n    case idle\r\n    case loading(message: String)\r\n    case content(data: String)\r\n    case error(title: String, message: String)\r\n}\r\n\r\nfunc updateUI(for state: ScreenState) {\r\n    switch state {\r\n    case .idle:\r\n        hideLoading()\r\n        hideError()\r\n        showIdleView()\r\n        \r\n    case .loading(let msg):\r\n        showLoading(message: msg)\r\n        \r\n    case .content(let data):\r\n        hideLoading()\r\n        showContent(data)\r\n        \r\n    case .error(let title, let msg):\r\n        hideLoading()\r\n        showError(title: title, message: msg)\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">7. Quick Summary \u2013 When to use what<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"sm\">Situation<\/th>\n<th data-col-size=\"xl\">Use this kind of enum<\/th>\n<th data-col-size=\"lg\">Typical example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"sm\">Simple fixed states<\/td>\n<td data-col-size=\"xl\">enum Direction { case north, south, east, west }<\/td>\n<td data-col-size=\"lg\">UI states, weather, roles<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">State + extra data<\/td>\n<td data-col-size=\"xl\">case success(data: T)<\/td>\n<td data-col-size=\"lg\">API responses, async results<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Error with details<\/td>\n<td data-col-size=\"xl\">case failure(code: Int, message: String)<\/td>\n<td data-col-size=\"lg\">Network, validation errors<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Raw value needed (String\/Int)<\/td>\n<td data-col-size=\"xl\">enum HTTPStatus: Int { case ok = 200 \u2026 }<\/td>\n<td data-col-size=\"lg\">API codes, persistence<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Need exhaustive checking<\/td>\n<td data-col-size=\"xl\">switch without default on enum<\/td>\n<td data-col-size=\"lg\">Compiler forces you to handle all cases<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">8. Small Practice \u2013 Try these<\/h3>\n<ol dir=\"auto\">\n<li>Create enum PaymentStatus with cases:\n<ul dir=\"auto\">\n<li>pending<\/li>\n<li>processing(amount: Double)<\/li>\n<li>completed(transactionID: String)<\/li>\n<li>failed(reason: String)<\/li>\n<\/ul>\n<\/li>\n<li>Write a function that switches on it and prints appropriate message<\/li>\n<li>Create enum APIResult&lt;T&gt; with success(T), failure(String) \u2192 Use pattern matching to handle both cases<\/li>\n<\/ol>\n<p dir=\"auto\">Paste your code here if you want feedback or want to see more elegant versions!<\/p>\n<p dir=\"auto\">What would you like to explore next?<\/p>\n<ul dir=\"auto\">\n<li><strong>Advanced pattern matching<\/strong> (if case let, guard case let, switch on tuples\u2026)<\/li>\n<li><strong>Enums with associated values<\/strong> in depth<\/li>\n<li><strong>RawRepresentable<\/strong> enums (String\/Int backed)<\/li>\n<li>Enums in <strong>SwiftUI<\/strong> (state management, view switching)<\/li>\n<li>Or move to another topic (optionals, arrays, map\/filter\/reduce, protocols\u2026)<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me \u2014 we\u2019ll continue in the same clear, detailed, patient style \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Why do we even need enums? (the most important intuition) In real life we often have a fixed number of possible states or categories: The weather is either sunny, cloudy, rainy, snowy\u2026 User&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[76],"tags":[],"class_list":["post-2734","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2734","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/comments?post=2734"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2734\/revisions"}],"predecessor-version":[{"id":2735,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2734\/revisions\/2735"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2734"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2734"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2734"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}