<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gamya </title>
    <description>The latest articles on DEV Community by Gamya  (@gamya_m).</description>
    <link>https://dev.to/gamya_m</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3691193%2Fa216f89b-ba3c-4643-b67c-ec28cc54d293.jpg</url>
      <title>DEV Community: Gamya </title>
      <link>https://dev.to/gamya_m</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gamya_m"/>
    <language>en</language>
    <item>
      <title>The Crash That Only Happened Sometimes — A SwiftUI Bug</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Sat, 25 Jul 2026 07:45:27 +0000</pubDate>
      <link>https://dev.to/gamya_m/the-crash-that-only-happened-sometimes-a-swiftui-bug-1kk5</link>
      <guid>https://dev.to/gamya_m/the-crash-that-only-happened-sometimes-a-swiftui-bug-1kk5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  I spent three hours debugging a SwiftUI crash that felt completely random. It wasn't random at all. It was me, a force unwrap, and a fundamental misunderstanding of when SwiftUI renders its views.
&lt;/h2&gt;

&lt;p&gt;Okay gather round because I need to tell you about the three hours I spent convinced I had found a bug in SwiftUI itself. I had not found a bug in SwiftUI. I had found a bug in my own assumptions, which is both more embarrassing and more educational, and I am sharing it here so you don't have to go through the same thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I was building a list-to-detail navigation flow. Classic stuff. You tap an item in a list, it navigates to a detail screen, the detail screen fetches and displays the selected item's full data. Nothing fancy. The kind of thing you've probably built or seen a dozen times.&lt;/p&gt;

&lt;p&gt;I had a view model managing the selected item state, and because I was moving fast and feeling a little overconfident, I declared it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@Published&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;selectedItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;!&lt;/code&gt; at the end. That little exclamation mark. That tiny, innocent-looking, completely catastrophic punctuation.&lt;/p&gt;

&lt;p&gt;For those who haven't encountered this particular flavour of Swift danger: that's an &lt;strong&gt;implicitly unwrapped optional&lt;/strong&gt;. It means the variable can technically be &lt;code&gt;nil&lt;/code&gt;, but you're telling Swift "trust me, it won't be." Swift says "okay" and doesn't make you check. Until it is &lt;code&gt;nil&lt;/code&gt;. And then your app explodes.&lt;/p&gt;

&lt;p&gt;My reasoning at the time was: &lt;em&gt;by the time the detail view renders, I'll have set selectedItem. It's fine. It'll be fine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Reader, it was not fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Crime Scene
&lt;/h2&gt;

&lt;p&gt;The crash started showing up in testing. But here's the thing that made it so maddening: &lt;strong&gt;it didn't happen every time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes I'd tap an item, the detail screen would appear, everything would be perfect. Sometimes I'd tap an item and the app would crash immediately with a cryptic EXC_BAD_INSTRUCTION on a line inside the view's &lt;code&gt;body&lt;/code&gt;. No useful stack trace. No clear reproduction steps. Just: sometimes crash, sometimes not.&lt;/p&gt;

&lt;p&gt;My first instinct was device-specific. Tested on different simulators. Nope.&lt;/p&gt;

&lt;p&gt;My second instinct was data-specific. Tested with different items. Nope.&lt;/p&gt;

&lt;p&gt;My third instinct, I am slightly embarrassed to admit, was that SwiftUI was doing something weird with navigation timing. I spent a genuinely non-trivial amount of time reading about NavigationStack rendering behaviour and convincing myself the framework had an edge case.&lt;/p&gt;

&lt;p&gt;It did not have an edge case. I had an edge case.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Investigation
&lt;/h2&gt;

&lt;p&gt;What finally broke it open was slowing down and actually tracing the execution order instead of staring at the crash line.&lt;/p&gt;

&lt;p&gt;Here's what I thought was happening:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User taps item&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selectedItem&lt;/code&gt; gets set in the view model&lt;/li&gt;
&lt;li&gt;SwiftUI navigates to detail view&lt;/li&gt;
&lt;li&gt;Detail view renders using &lt;code&gt;selectedItem&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's what was &lt;strong&gt;actually&lt;/strong&gt; happening:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User taps item&lt;/li&gt;
&lt;li&gt;SwiftUI begins evaluating and rendering the destination view&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;selectedItem&lt;/code&gt; is still nil during this initial render pass&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The force unwrap fires&lt;/li&gt;
&lt;li&gt;Crash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SwiftUI doesn't wait politely for your async state to be ready before it starts rendering. It evaluates the view body, and if your view body contains a force-unwrapped optional that isn't set yet, it will crash during that evaluation. The "sometimes" quality of the bug came from timing — on faster devices or with cached data, &lt;code&gt;selectedItem&lt;/code&gt; was set fast enough that the render pass caught it in time. On slower paths, it didn't.&lt;/p&gt;

&lt;p&gt;The crash wasn't random. It was a race condition I had created with an exclamation mark.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;Once I understood the actual problem, the fix was straightforward. I replaced the implicitly unwrapped optional with a safe optional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before — ticking time bomb&lt;/span&gt;
&lt;span class="kd"&gt;@Published&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;selectedItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

&lt;span class="c1"&gt;// After — honest about what this can be&lt;/span&gt;
&lt;span class="kd"&gt;@Published&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;selectedItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And updated the SwiftUI view to handle every state the data could actually be in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before — assumes selectedItem is always there&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;ItemDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectedItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// After — handles every intermediate state explicitly&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;ProgressView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectedItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;ItemDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Something went wrong."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The crash vanished immediately. The fix took about ten minutes. The debugging took three hours.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Actually Learned
&lt;/h2&gt;

&lt;p&gt;The technical lesson is: &lt;strong&gt;in SwiftUI, your UI must be able to render safely for every intermediate state.&lt;/strong&gt; SwiftUI is declarative and reactive — it can and will evaluate your view body at any point, including before your async operations complete. If your view assumes state that hasn't arrived yet, it will fail exactly when that assumption turns out to be wrong.&lt;/p&gt;

&lt;p&gt;The deeper lesson is: implicitly unwrapped optionals are almost never the right call in a SwiftUI view model. They exist for situations where initialization order makes it genuinely impossible to set a value at declaration time — like &lt;code&gt;@IBOutlet&lt;/code&gt; connections in UIKit. They are not a way to skip handling states you find inconvenient. Every time you write &lt;code&gt;!&lt;/code&gt; to avoid dealing with an optional, you're writing a crash that just hasn't happened yet.&lt;/p&gt;

&lt;p&gt;The thing that still makes me a little sheepish: I knew this, in the abstract. I'd read about IUOs. I understood optionals. I just got lazy in a moment of "this will clearly be set by the time it matters."&lt;/p&gt;

&lt;p&gt;SwiftUI disagreed. SwiftUI was right.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI tools were used to help with grammar and structure.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>Swift Classes — The Four Ways Variables and Constants Can Combine 🎭</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Thu, 23 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-the-four-ways-variables-and-constants-can-combine-3mjj</link>
      <guid>https://dev.to/gamya_m/swift-classes-the-four-ways-variables-and-constants-can-combine-3mjj</guid>
      <description>&lt;p&gt;A constant class can have its properties changed. A constant struct can't. This sounds inconsistent until you remember the signpost — and then it makes perfect sense.&lt;/p&gt;




&lt;p&gt;There's a moment when you're learning Swift where something happens that makes absolutely no sense on the surface. You create a constant class instance — a &lt;code&gt;let&lt;/code&gt; — and then you change one of its properties. And it works. Swift lets you do it without complaint.&lt;/p&gt;

&lt;p&gt;Meanwhile, you try the same thing with a constant struct and Swift immediately shuts you down.&lt;/p&gt;

&lt;p&gt;Same keyword. Different behavior. What's going on?&lt;/p&gt;

&lt;p&gt;The answer, as with most things in the classes chapter, comes back to the signpost. 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Reminder About Signposts
&lt;/h2&gt;

&lt;p&gt;When you create a class instance and assign it to a variable, what you're actually holding is a &lt;strong&gt;signpost pointing to the data&lt;/strong&gt; — not the data itself. The class instance lives somewhere in memory, and your variable just tells Swift where to find it.&lt;/p&gt;

&lt;p&gt;This is the fundamental difference between classes and structs. Structs hold their data directly. Classes hold a reference to their data.&lt;/p&gt;

&lt;p&gt;Keep that in mind, because it explains everything that follows.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Constant That Isn't Constant
&lt;/h2&gt;

&lt;p&gt;Here's the thing that trips people up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ✅ This works fine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait. &lt;code&gt;naruto&lt;/code&gt; is a &lt;code&gt;let&lt;/code&gt;. How is this allowed?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;let naruto&lt;/code&gt; doesn't mean "the Ninja named Naruto is frozen forever." It means "the signpost called &lt;code&gt;naruto&lt;/code&gt; is locked in place — it will always point to this specific Ninja instance."&lt;/p&gt;

&lt;p&gt;The signpost is constant. The data it points to is not.&lt;/p&gt;

&lt;p&gt;Changing &lt;code&gt;naruto.powerLevel&lt;/code&gt; doesn't move the signpost. It doesn't replace the Ninja with a different Ninja. It just walks to the end of the signpost and changes a value there. The signpost itself didn't go anywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  What &lt;code&gt;let&lt;/code&gt; Actually Locks
&lt;/h2&gt;

&lt;p&gt;So what would &lt;code&gt;let naruto&lt;/code&gt; prevent?&lt;/p&gt;

&lt;p&gt;This:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Not allowed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;That's&lt;/em&gt; what you can't do. You can't point &lt;code&gt;naruto&lt;/code&gt; at a completely different Ninja. The signpost is locked — you can't turn it to face a new direction. But you can absolutely change things at the end of the signpost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Structs Work Differently
&lt;/h2&gt;

&lt;p&gt;Now here's why constant structs don't allow property changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;goku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Goku"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goku&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9002&lt;/span&gt; &lt;span class="c1"&gt;// ❌ This won't compile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structs don't use signposts. They hold their data directly. So &lt;code&gt;let goku&lt;/code&gt; means "the value stored here is constant" — and that value includes everything inside it.&lt;/p&gt;

&lt;p&gt;Think of it this way: a struct is like the number 5. When you write &lt;code&gt;let x = 5&lt;/code&gt;, you're saying x is 5, permanently. You can't say "well, I'll keep x but just change one digit of the 5." The 5 is the whole thing. Changing any part of a struct means replacing the entire struct — and you can't replace a constant.&lt;/p&gt;

&lt;p&gt;So with structs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;goku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Goku"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goku&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9002&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Works — goku is a var, so the whole struct can be replaced&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;var goku&lt;/code&gt;, Swift can swap out the entire struct value for a new one with the updated property. With &lt;code&gt;let goku&lt;/code&gt;, it can't, because that would mean destroying and recreating a constant.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Combinations
&lt;/h2&gt;

&lt;p&gt;This gives us four different situations, and they're all worth understanding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Constant class, constant property&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// naruto.powerLevel = 9001 ❌ — can't change a let property&lt;/span&gt;
&lt;span class="c1"&gt;// naruto = Ninja(...) ❌ — can't reassign the signpost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signpost is locked, and the name tag is written in permanent ink. Nothing changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Constant class, variable property&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ✅ — can change the var property&lt;/span&gt;
&lt;span class="c1"&gt;// naruto = Ninja(...) ❌ — still can't reassign the signpost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signpost is locked, but the data at the end of it can still be updated. This is the one that surprises people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Variable class, constant property&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// naruto.powerLevel = 9001 ❌ — can't change a let property&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ✅ — can point at a new Ninja&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can swing the signpost to point at a completely different ninja, but once you're there, their permanent ink properties can't be changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Variable class, variable property&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maximum flexibility. The signpost can move, and the data can change. This is the most permissive option.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Nice Bonus: No &lt;code&gt;mutating&lt;/code&gt; Needed
&lt;/h2&gt;

&lt;p&gt;Remember from the structs chapter how methods that changed properties had to be marked &lt;code&gt;mutating&lt;/code&gt;? Classes don't have that requirement.&lt;/p&gt;

&lt;p&gt;The reason structs need &lt;code&gt;mutating&lt;/code&gt; is so Swift can protect you from calling a property-changing method on a constant struct — it can check at compile time whether the method would be allowed. With classes, the check is simpler: just look at whether the property itself is &lt;code&gt;var&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt;. Swift doesn't need the &lt;code&gt;mutating&lt;/code&gt; label to know what's allowed, because the class instance's own constancy doesn't affect its properties the same way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;let&lt;/code&gt; on a class locks the &lt;strong&gt;signpost&lt;/strong&gt;, not the &lt;strong&gt;data&lt;/strong&gt;. You can still change variable properties on a constant class — you just can't point that constant at a different instance entirely.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;let&lt;/code&gt; on a struct locks &lt;strong&gt;everything&lt;/strong&gt;, because the struct &lt;em&gt;is&lt;/em&gt; the data. There's no signpost to separate the container from the contents.&lt;/p&gt;

&lt;p&gt;Once that distinction is clear, the four combinations stop feeling arbitrary and start feeling like exactly the right behavior for each type. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>ios</category>
      <category>programming</category>
    </item>
    <item>
      <title>Swift Classes — Deinitializers and How Swift Cleans Up After Itself 🧹</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Wed, 22 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-deinitializers-and-how-swift-cleans-up-after-itself-mk3</link>
      <guid>https://dev.to/gamya_m/swift-classes-deinitializers-and-how-swift-cleans-up-after-itself-mk3</guid>
      <description>&lt;h2&gt;
  
  
  Every class instance is eventually destroyed. Swift gives you a way to know exactly when that happens — and the story of how it decides when to pull the trigger is surprisingly interesting.
&lt;/h2&gt;

&lt;p&gt;Here's something you've probably never thought about: what happens to your objects when you're done with them?&lt;/p&gt;

&lt;p&gt;With structs, the answer is simple. A struct lives as long as whatever owns it. Create a struct inside a function, the function ends, the struct is gone. Clean, predictable, boring in the best way.&lt;/p&gt;

&lt;p&gt;Classes are messier. Remember — when you "copy" a class, you're not copying the data, you're copying a signpost pointing to the data. That means multiple parts of your code might be holding onto a reference to the same class instance. So when does that instance actually get destroyed? When the first reference goes away? The last?&lt;/p&gt;

&lt;p&gt;The answer is: the last one. And Swift has a whole system behind the scenes to track it. 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic Reference Counting — The Invisible Accountant
&lt;/h2&gt;

&lt;p&gt;Behind every class instance in Swift, there's a hidden counter. Every time you create a new reference to a class instance — by assigning it to a variable, passing it to a function, storing it in an array — Swift adds 1 to that counter. Every time one of those references goes away, Swift subtracts 1.&lt;/p&gt;

&lt;p&gt;When the counter hits zero, Swift knows: nobody is looking at this anymore. It's safe to destroy it.&lt;/p&gt;

&lt;p&gt;This system is called &lt;strong&gt;Automatic Reference Counting&lt;/strong&gt;, or ARC. You never have to manage it yourself — Swift handles it invisibly, continuously, for every class instance in your app.&lt;/p&gt;

&lt;p&gt;Structs don't need ARC because each copy of a struct is its own independent piece of data. When a struct variable goes away, the data goes with it. Simple. No counting needed.&lt;/p&gt;

&lt;p&gt;Classes need ARC precisely because the signpost system means multiple variables can point at the same data. Without counting references, Swift would have no way to know when the last one was gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Enter the Deinitializer
&lt;/h2&gt;

&lt;p&gt;When Swift's reference counter hits zero and a class instance is about to be destroyed, Swift will call a special method called the &lt;strong&gt;deinitializer&lt;/strong&gt; — written as &lt;code&gt;deinit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's the counterpart to &lt;code&gt;init&lt;/code&gt;. Where &lt;code&gt;init&lt;/code&gt; runs when an instance is created, &lt;code&gt;deinit&lt;/code&gt; runs when the last reference to it disappears.&lt;/p&gt;

&lt;p&gt;Let's see it in action with an anime training camp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; has opened! 🏕️"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;deinit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; has been abandoned. Training is over."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create some camps and watch them get destroyed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;camp1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Konoha Training Grounds"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;camp2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sand Village Camp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;camp3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TrainingCamp&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;camp1&lt;/span&gt; &lt;span class="c1"&gt;// camp1 and camp3 now point to the same camp&lt;/span&gt;

&lt;span class="n"&gt;camp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;// reference count for Konoha drops to 1 (camp3 still holds it)&lt;/span&gt;
&lt;span class="n"&gt;camp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;// reference count for Sand Village drops to 0 — deinit fires!&lt;/span&gt;
&lt;span class="n"&gt;camp3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;// reference count for Konoha drops to 0 — deinit fires!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Konoha Training Grounds has opened! 🏕️
Sand Village Camp has opened! 🏕️
Sand Village Camp has been abandoned. Training is over.
Konoha Training Grounds has been abandoned. Training is over.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice: &lt;code&gt;camp2&lt;/code&gt; fires its deinitializer as soon as &lt;code&gt;camp2 = nil&lt;/code&gt; because that was the only reference. Konoha's deinitializer doesn't fire until &lt;code&gt;camp3 = nil&lt;/code&gt;, because even after &lt;code&gt;camp1&lt;/code&gt; was set to nil, &lt;code&gt;camp3&lt;/code&gt; was still keeping the count at 1.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Few Things Worth Knowing About &lt;code&gt;deinit&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can't call it yourself.&lt;/strong&gt; &lt;code&gt;deinit&lt;/code&gt; is called by Swift automatically when the reference count hits zero. You can define it, but you can't trigger it manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It takes no parameters.&lt;/strong&gt; Unlike &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;deinit&lt;/code&gt; doesn't accept any arguments. It runs with no input — it just gets told "you're being destroyed, do whatever you need to do."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to put it?&lt;/strong&gt; Technically anywhere in the class. But there's a lovely convention: put it at the end of the class body. Code should read like a chapter in a book, and &lt;code&gt;deinit&lt;/code&gt; is the final scene — the &lt;em&gt;fin&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Other Thing About Variables in Classes
&lt;/h2&gt;

&lt;p&gt;While we're on the topic of classes behaving differently from structs, there's one more quirk worth naming.&lt;/p&gt;

&lt;p&gt;Remember from the structs chapter: if you create a &lt;code&gt;let&lt;/code&gt; constant struct, nothing about it can change — not its properties, not anything.&lt;/p&gt;

&lt;p&gt;Classes don't work that way. A &lt;code&gt;let&lt;/code&gt; class means "this variable will always point to the same instance." It does not mean "the instance can't change."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ✅ This is fine!&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ❌ This isn't — you can't reassign the signpost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;let naruto&lt;/code&gt; means naruto's signpost is locked — it will always point to the same &lt;code&gt;Ninja&lt;/code&gt; instance. But the data at the end of that signpost? Completely free to change.&lt;/p&gt;

&lt;p&gt;This makes sense once you think about the signpost analogy. &lt;code&gt;let&lt;/code&gt; locks the signpost in place. It says nothing about what the signpost points to.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters in Real iOS Development
&lt;/h2&gt;

&lt;p&gt;ARC and deinitializers matter most when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're managing resources that need explicit cleanup — network connections, file handles, observers, timers&lt;/li&gt;
&lt;li&gt;You need to debug memory issues and want to know exactly when objects are being created and destroyed&lt;/li&gt;
&lt;li&gt;You're working with complex object graphs where multiple things hold references to the same data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For everyday SwiftUI development you won't write &lt;code&gt;deinit&lt;/code&gt; constantly. But understanding that it exists — and understanding &lt;em&gt;why&lt;/em&gt; it exists (because ARC needs a hook for cleanup) — helps you understand the memory model of your app rather than just hoping things work out.&lt;/p&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;Swift counts how many things are pointing at each class instance. When the count hits zero, it calls &lt;code&gt;deinit&lt;/code&gt; and destroys the object. That's ARC in a nutshell.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;let&lt;/code&gt; on a class means the signpost is constant — not the data it points to. That's the quirk that trips people up until the signpost analogy finally clicks. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>ios</category>
      <category>programming</category>
    </item>
    <item>
      <title>Swift Classes — Why Copying a Class Isn't What You Think 📋</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Tue, 21 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-why-copying-a-class-isnt-what-you-think-31ip</link>
      <guid>https://dev.to/gamya_m/swift-classes-why-copying-a-class-isnt-what-you-think-31ip</guid>
      <description>&lt;p&gt;Okay. This one is going to feel weird at first. I'm going to warn you in advance so you don't think something is broken when you try it.&lt;/p&gt;

&lt;p&gt;Here's what's going to happen: you're going to create a class, make a copy of it, change something in the copy, and then discover that the original changed too.&lt;/p&gt;

&lt;p&gt;And you're going to say: "That's not how copying works."&lt;/p&gt;

&lt;p&gt;And I'm going to say: "You're right. But for classes, that's exactly how it works. Sit down. Let's talk." 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  The Moment That Breaks Your Brain
&lt;/h2&gt;

&lt;p&gt;Let's create a simple class for a ninja character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create an instance, copy it, and change something in the copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;naruto&lt;/span&gt;

&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// "Sasuke" 😱&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "Sasuke"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait. We changed &lt;code&gt;naruto2&lt;/code&gt;, but &lt;code&gt;naruto&lt;/code&gt; changed too?&lt;/p&gt;

&lt;p&gt;Yes. That's not a bug. That's how classes work.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Signpost Analogy
&lt;/h2&gt;

&lt;p&gt;Here's the mental model that makes this click.&lt;/p&gt;

&lt;p&gt;When you create a struct, Swift stores the actual data directly in the variable. Copying a struct is like photocopying a document — you get two completely separate pieces of paper. Change one, the other is untouched.&lt;/p&gt;

&lt;p&gt;When you create a class, Swift stores the data somewhere in memory and gives your variable a &lt;strong&gt;signpost pointing to that location&lt;/strong&gt;. Copying a class doesn't copy the data — it copies the signpost. Now you have two signposts pointing at the same piece of data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// naruto is a signpost pointing to data: {name: "Naruto", powerLevel: 9000}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;naruto&lt;/span&gt;
&lt;span class="c1"&gt;// naruto2 is a SECOND signpost pointing to the SAME data&lt;/span&gt;

&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;
&lt;span class="c1"&gt;// You followed naruto2's signpost and changed the data it points to&lt;/span&gt;
&lt;span class="c1"&gt;// naruto's signpost points to the SAME data, so naruto.name is also "Sasuke"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's only one piece of data. Both variables are just different ways of pointing at it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Would Swift Do This On Purpose?
&lt;/h2&gt;

&lt;p&gt;This isn't a mistake or an oversight. It's a deliberate design decision, and it's actually useful.&lt;/p&gt;

&lt;p&gt;Think about a real iOS app. Say you have a user profile that shows up on a settings screen, a home screen, and a notification. If all three screens have their own independent copy of the user data, and the user changes their username — now you have to update three separate copies. Miss one and you have inconsistent data showing in different parts of your app.&lt;/p&gt;

&lt;p&gt;With a class, all three screens are looking at the same piece of data through their own signpost. Change the username once, and every screen that holds a reference to that user sees the updated value automatically. That's exactly what you want for shared state.&lt;/p&gt;

&lt;p&gt;This is why Swift calls classes &lt;strong&gt;reference types&lt;/strong&gt; — you're passing around references (signposts) to data, not copies of the data itself. Structs are &lt;strong&gt;value types&lt;/strong&gt; — the value is the data, and copying creates a fresh independent copy.&lt;/p&gt;




&lt;h2&gt;
  
  
  So How Do You Make a True Copy?
&lt;/h2&gt;

&lt;p&gt;Sometimes you genuinely do want a separate copy — two independent ninjas that can change without affecting each other. Swift doesn't give you that automatically for classes, but you can create it yourself by writing a &lt;code&gt;copy()&lt;/code&gt; method that creates a fresh instance with the same values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you want a true independent copy, you call &lt;code&gt;copy()&lt;/code&gt; explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Sasuke"&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// "Naruto" — unchanged ✅&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "Sasuke" — only this one changed ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two signposts, two separate pieces of data. The copy() method creates a brand new &lt;code&gt;Ninja&lt;/code&gt; instance in memory with the same starting values — so now each variable has its own data to work with.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing a Class Sends a Message
&lt;/h2&gt;

&lt;p&gt;Here's something worth holding onto that goes beyond the technical mechanics:&lt;/p&gt;

&lt;p&gt;When you choose to use a class instead of a struct, you're making a statement about how you expect the data to be used. You're saying: &lt;strong&gt;"I want multiple parts of my code to share and observe the same piece of data."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you choose a struct, you're saying: &lt;strong&gt;"Each owner should get their own independent copy."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most Swift developers lean toward structs by default precisely because the copy-is-a-copy behavior is simpler and easier to reason about. You reach for a class when shared, synchronized data is exactly what you need — like a data model that needs to be observed and updated across multiple views in a SwiftUI app.&lt;/p&gt;

&lt;p&gt;The signpost is a feature, not a bug. You just have to know it's there.&lt;/p&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Copying a class copies the signpost, not the data.&lt;/strong&gt; Both copies end up pointing at the same underlying object, so changing one changes what the other sees too.&lt;/p&gt;

&lt;p&gt;If you want a true independent copy, write a &lt;code&gt;copy()&lt;/code&gt; method that creates a new instance. Swift won't do it for you automatically — which is intentional, because it forces you to be explicit about something that matters. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>swiftui</category>
      <category>ios</category>
      <category>programming</category>
    </item>
    <item>
      <title>Swift Classes — Initializers and the super.init() Rule 🏗️</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-initializers-and-the-superinit-rule-9hn</link>
      <guid>https://dev.to/gamya_m/swift-classes-initializers-and-the-superinit-rule-9hn</guid>
      <description>&lt;h2&gt;
  
  
  Class initializers in Swift come with one golden rule that catches everyone out the first time. Let's talk about what it is, why it exists, and how to stop forgetting it.
&lt;/h2&gt;

&lt;p&gt;Okay so we need to talk about initializers again. I know, I know — we covered them in the structs chapter. But classes have a twist that trips people up the first time they hit it, and it's worth slowing down on before you run into it at 11pm debugging something that seems like it should be obvious.&lt;/p&gt;

&lt;p&gt;Here's the short version of what we're going to learn today:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When a child class has its own initializer, it must call the parent's initializer — and it has to do it after setting up its own stuff first.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's it. That's the rule. But let's actually understand why, because "just do it" is a terrible way to remember something. 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting the Scene
&lt;/h2&gt;

&lt;p&gt;Let's build a ninja academy system. Every person in the ninja world has a &lt;code&gt;chakraType&lt;/code&gt; — whether they use fire, wind, water, earth, or lightning chakra. That's a property that belongs to everyone, so it lives in the parent class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chakraType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough. Now let's say we want a &lt;code&gt;StudentNinja&lt;/code&gt; that inherits from &lt;code&gt;NinjaAcademy&lt;/code&gt; but also has a &lt;code&gt;rank&lt;/code&gt; — like Genin, Chunin, or Jonin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;StudentNinja&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks reasonable. But Swift will refuse to build it. And the error message will say something like: &lt;em&gt;"Super.init isn't called on all paths before returning from initializer."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Swift is Refusing
&lt;/h2&gt;

&lt;p&gt;Here's the problem. &lt;code&gt;NinjaAcademy&lt;/code&gt; has a property called &lt;code&gt;chakraType&lt;/code&gt;. It's required — there's no default value, and Swift's golden rule for initializers is &lt;strong&gt;every property must have a value by the time initialization is done&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;StudentNinja&lt;/code&gt; is created, it inherits &lt;code&gt;chakraType&lt;/code&gt; from &lt;code&gt;NinjaAcademy&lt;/code&gt;. But who sets it? &lt;code&gt;StudentNinja&lt;/code&gt;'s initializer doesn't mention it. And if nobody sets it, &lt;code&gt;chakraType&lt;/code&gt; ends up without a value — which Swift will not allow.&lt;/p&gt;

&lt;p&gt;The solution is to accept &lt;code&gt;chakraType&lt;/code&gt; in &lt;code&gt;StudentNinja&lt;/code&gt;'s initializer too, and then pass it up to &lt;code&gt;NinjaAcademy&lt;/code&gt; using &lt;code&gt;super.init()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;StudentNinja&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it works. Let's break down what's happening on those two critical lines.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Order Matters: Your Stuff First, Then Super
&lt;/h2&gt;

&lt;p&gt;Notice the order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;           &lt;span class="c1"&gt;// 1. Set your own properties first&lt;/span&gt;
&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 2. Then call the parent's initializer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This order is not optional. Swift enforces it. If you try to call &lt;code&gt;super.init()&lt;/code&gt; before setting &lt;code&gt;self.rank&lt;/code&gt;, Swift will refuse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ This won't work — wrong order&lt;/span&gt;
&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="c1"&gt;// too late — super.init already ran&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is safety. Swift wants to make sure the current class's own properties are fully set up before it hands control to the parent class. If something went wrong during &lt;code&gt;super.init()&lt;/code&gt;, you'd at least know your own class's properties were in a valid state.&lt;/p&gt;

&lt;p&gt;Think of it like building a house. You have to finish your own floor before you can ask the architect to come check the whole building. The architect (super.init) needs to know the floor they're standing on is solid.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using the Finished Class
&lt;/h2&gt;

&lt;p&gt;With the initializers in place, you can now create a &lt;code&gt;StudentNinja&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sakura&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;StudentNinja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Fire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Genin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sakura&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "Fire" — inherited from NinjaAcademy&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sakura&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// "Genin" — defined in StudentNinja&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both properties are accessible, both are set correctly. &lt;code&gt;sakura&lt;/code&gt; is a &lt;code&gt;StudentNinja&lt;/code&gt;, but she also has everything &lt;code&gt;NinjaAcademy&lt;/code&gt; defined because that's what inheritance gives you.&lt;/p&gt;




&lt;h2&gt;
  
  
  What If the Subclass Has No Custom Initializer?
&lt;/h2&gt;

&lt;p&gt;Here's the good news: if your subclass doesn't add any new properties that need setting, you don't need to write an initializer at all. Swift will just inherit the parent's automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;EliteNinja&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;specialMove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; chakra for a special attack!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;kakashi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;EliteNinja&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Lightning"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;kakashi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;specialMove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// "Using Lightning chakra for a special attack!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;EliteNinja&lt;/code&gt; adds a method but no new properties — so it inherits &lt;code&gt;NinjaAcademy&lt;/code&gt;'s initializer for free and you don't have to write anything. More precisely: the &lt;code&gt;super.init()&lt;/code&gt; requirement kicks in whenever your subclass defines its own designated initializer — even if it adds no new properties. The common case is adding properties (like &lt;code&gt;rank&lt;/code&gt; above), but the rule is really about the initializer chain, not the properties themselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;super&lt;/code&gt; Is Not Just for Initializers
&lt;/h2&gt;

&lt;p&gt;While we're here — &lt;code&gt;super&lt;/code&gt; isn't limited to &lt;code&gt;init&lt;/code&gt;. You can use it to call any method from the parent class, which is useful when you're overriding a method but still want to run the parent's version too.&lt;/p&gt;

&lt;p&gt;For this to work, the method needs to exist on the parent class first. Let's add one to &lt;code&gt;NinjaAcademy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chakraType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Training with &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; chakra..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;Hokage&lt;/code&gt; can override it and call the parent's version using &lt;code&gt;super&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NinjaAcademy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// runs NinjaAcademy's version first&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; also reviews mission reports after training."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;chakraType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Wind"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Seventh Hokage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// "Training with Wind chakra..."&lt;/span&gt;
&lt;span class="c1"&gt;// "Seventh Hokage also reviews mission reports after training."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same pattern: &lt;code&gt;super&lt;/code&gt; gives you access to the parent, whether you're in an initializer or a regular method.&lt;/p&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;The rule that catches everyone: &lt;strong&gt;when your child class has its own initializer, set your own properties first, then call &lt;code&gt;super.init()&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Get that order right and everything works. Get it backwards and Swift will stop you immediately. It feels pedantic until you understand why — Swift is making sure every single property has a value before initialization completes, no matter how deep the inheritance chain goes. That's not pedantry, that's safety. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>programming</category>
      <category>ios</category>
      <category>development</category>
    </item>
    <item>
      <title>Swift Classes — Inheritance, Override, and the final Keyword 🧬</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Sun, 19 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-inheritance-override-and-the-final-keyword-3044</link>
      <guid>https://dev.to/gamya_m/swift-classes-inheritance-override-and-the-final-keyword-3044</guid>
      <description>&lt;p&gt;What if you could take an existing class and say "I want everything this already does, plus a few things of my own"? That's inheritance. Let's talk about it.&lt;/p&gt;

&lt;p&gt;Okay so here's a thought experiment.&lt;/p&gt;

&lt;p&gt;Imagine you're building an anime RPG. You need a &lt;code&gt;Ninja&lt;/code&gt; class. You create it, give it a &lt;code&gt;name&lt;/code&gt;, a &lt;code&gt;village&lt;/code&gt;, and a method called &lt;code&gt;fight()&lt;/code&gt;. Great. Done.&lt;/p&gt;

&lt;p&gt;Then you realise you also need a &lt;code&gt;Hokage&lt;/code&gt; class. A Hokage is still a ninja — they have a name, they belong to a village, they can fight. But they also have extra responsibilities. They lead. They make speeches. They sign off on missions.&lt;/p&gt;

&lt;p&gt;Now you have a choice. You could copy and paste everything from &lt;code&gt;Ninja&lt;/code&gt; into &lt;code&gt;Hokage&lt;/code&gt;. But that's a nightmare — every time you update &lt;code&gt;Ninja&lt;/code&gt;, you'd have to update &lt;code&gt;Hokage&lt;/code&gt; too, and if you forget, the two drift apart and weird bugs show up.&lt;/p&gt;

&lt;p&gt;Or you could use &lt;strong&gt;inheritance&lt;/strong&gt;. Which is Swift saying: "Just tell me what's the same and what's different, and I'll handle the rest." 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  How Inheritance Works
&lt;/h2&gt;

&lt;p&gt;Here's the base class — the &lt;strong&gt;parent&lt;/strong&gt; (or "superclass"):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;village&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; engages in battle!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;printSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; is a ninja from &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now here's a &lt;strong&gt;child class&lt;/strong&gt; (or "subclass") that inherits from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"String"&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"String) {"&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;giveOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; commands: protect the village!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;: Ninja&lt;/code&gt; after &lt;code&gt;Hokage&lt;/code&gt; is what makes it a subclass. That one colon gives &lt;code&gt;Hokage&lt;/code&gt; everything &lt;code&gt;Ninja&lt;/code&gt; has — &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;village&lt;/code&gt;, &lt;code&gt;fight()&lt;/code&gt;, &lt;code&gt;printSummary()&lt;/code&gt; — for free, without copying a single line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Konoha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Seventh Hokage&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="c1"&gt;// "Naruto engages in battle!" — inherited from Ninja&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;giveOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c1"&gt;// "Seventh Hokage Naruto commands: protect the village!"&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;printSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// "Naruto is a ninja from Konoha." — also inherited&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;naruto&lt;/code&gt; is a &lt;code&gt;Hokage&lt;/code&gt;, but Swift knows he's also a &lt;code&gt;Ninja&lt;/code&gt;, so all the &lt;code&gt;Ninja&lt;/code&gt; methods work on him without any extra effort.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When You Want to Change an Inherited Method?
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. What if &lt;code&gt;Hokage&lt;/code&gt;'s version of &lt;code&gt;printSummary()&lt;/code&gt; should say something different from &lt;code&gt;Ninja&lt;/code&gt;'s version? After all, "Naruto is a ninja from Konoha" is technically accurate but undersells the situation a bit.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;overriding&lt;/strong&gt; — replacing a parent's method with your own version. And Swift makes you be very explicit about it by requiring the &lt;code&gt;override&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;giveOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; commands: protect the village!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;printSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; is the &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; of &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; — show some respect."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you call &lt;code&gt;printSummary()&lt;/code&gt; on a &lt;code&gt;Hokage&lt;/code&gt;, you get the Hokage version. Call it on a plain &lt;code&gt;Ninja&lt;/code&gt;, you get the Ninja version. Swift figures out which one to use based on what the object actually is.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does Swift Force You to Write &lt;code&gt;override&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;This might seem like extra typing for no reason, but &lt;code&gt;override&lt;/code&gt; is actually doing two important jobs at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job 1 — It stops accidental overrides.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you create a method in your subclass called &lt;code&gt;printSummary()&lt;/code&gt; not realising the parent already has one. Without &lt;code&gt;override&lt;/code&gt;, you'd silently replace the parent's behaviour and wonder why things stopped working. With &lt;code&gt;override&lt;/code&gt; required, Swift stops you: "Hey, you're replacing something that exists. Was that on purpose?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job 2 — It stops override typos.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you meant to override &lt;code&gt;printSummary()&lt;/code&gt; but you accidentally typed &lt;code&gt;printSumary()&lt;/code&gt; (one m). Without the &lt;code&gt;override&lt;/code&gt; check, Swift would just create a brand new method with a typo in the name and your override would silently do nothing. With &lt;code&gt;override&lt;/code&gt;, Swift goes: "You said override, but there's nothing in the parent called &lt;code&gt;printSumary&lt;/code&gt;. Check your spelling."&lt;/p&gt;

&lt;p&gt;It's one keyword that catches two completely different categories of mistakes. Not bad.&lt;/p&gt;




&lt;h2&gt;
  
  
  What About Adding to an Inherited Method Instead of Replacing It?
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't want to completely replace the parent's method — you just want to run the parent's version and then add something on top. You can do that with &lt;code&gt;super&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;printSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;printSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// runs Ninja's version first&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"...and also the &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; of &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;super&lt;/code&gt; refers to the parent class. Calling &lt;code&gt;super.printSummary()&lt;/code&gt; runs whatever &lt;code&gt;Ninja&lt;/code&gt; defined, and then you can add your own lines after it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The &lt;code&gt;final&lt;/code&gt; Keyword — "Nobody Inherits From This"
&lt;/h2&gt;

&lt;p&gt;Sometimes you build a class and you know, very firmly, that nobody should ever subclass it. Maybe it does something critical where overriding the wrong method would cause weird, hard-to-debug behavior. Maybe you just don't want to support that level of customization.&lt;/p&gt;

&lt;p&gt;That's what &lt;code&gt;final&lt;/code&gt; is for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Akatsuki&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;revealPlan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The plan... is Pain's."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mark a class as &lt;code&gt;final&lt;/code&gt; and Swift will refuse to let anyone inherit from it. Try it and you'll get a compile error immediately.&lt;/p&gt;

&lt;p&gt;Apple uses this in their own frameworks. There's a class called &lt;code&gt;AVPlayerViewController&lt;/code&gt; — for playing videos — where Apple's documentation essentially says "do not subclass this, things will break in undefined ways." In older Objective-C code they had to say that in plain English and hope developers read it. In Swift, &lt;code&gt;final&lt;/code&gt; enforces it in the compiler.&lt;/p&gt;

&lt;p&gt;Think of &lt;code&gt;final&lt;/code&gt; as documentation you can't ignore. It doesn't just tell future developers not to subclass — it makes it physically impossible.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inheritance&lt;/td&gt;
&lt;td&gt;A child class gets all properties and methods from its parent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;: ParentClass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The syntax that makes one class inherit from another&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;override&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required when replacing a parent's method with your own version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;super&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Calls the parent class's version of a method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;final&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prevents anyone from inheriting from this class&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;Inheritance is powerful, but it's also easy to over-use. The guideline most Swift developers follow is: &lt;strong&gt;only inherit when the child genuinely is a more specific version of the parent.&lt;/strong&gt; A &lt;code&gt;Hokage&lt;/code&gt; is a &lt;code&gt;Ninja&lt;/code&gt; — that's genuine. A &lt;code&gt;Village&lt;/code&gt; is not a &lt;code&gt;Ninja&lt;/code&gt; — that would be strange and wrong.&lt;/p&gt;

&lt;p&gt;If you're not sure whether inheritance is the right tool, it probably isn't. Composition (putting objects inside other objects) is usually cleaner. But when inheritance is the right call, &lt;code&gt;override&lt;/code&gt; and &lt;code&gt;final&lt;/code&gt; are there to make sure it doesn't quietly go sideways on you. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>development</category>
      <category>programming</category>
      <category>ios</category>
    </item>
    <item>
      <title>Swift Classes — Everything You Knew About Structs Just Got More Complicated</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Sat, 18 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-classes-everything-you-knew-about-structs-just-got-more-complicated-2162</link>
      <guid>https://dev.to/gamya_m/swift-classes-everything-you-knew-about-structs-just-got-more-complicated-2162</guid>
      <description>&lt;p&gt;Okay so. We need to talk about classes.&lt;/p&gt;

&lt;p&gt;If you've been following along with this series, you're probably feeling pretty comfortable with structs at this point. You've got properties, methods, initializers, computed properties, access control, the whole thing. You feel good. You feel ready.&lt;/p&gt;

&lt;p&gt;And then Swift says: "Great. Now meet classes."&lt;/p&gt;

&lt;p&gt;And you go: "...are those just structs with a different name?"&lt;/p&gt;

&lt;p&gt;And Swift goes: "No."&lt;/p&gt;

&lt;p&gt;And you go: "They look exactly like structs."&lt;/p&gt;

&lt;p&gt;And Swift goes: "They are not exactly like structs. Sit down."&lt;/p&gt;

&lt;p&gt;So. Let's sit down. 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  On the Surface, Classes Look Identical
&lt;/h2&gt;

&lt;p&gt;Here's a class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;powerLevel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; — Power Level: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a struct doing the exact same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; — Power Level: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spot the difference? One says &lt;code&gt;class&lt;/code&gt;, one says &lt;code&gt;struct&lt;/code&gt;. The struct doesn't need a custom &lt;code&gt;init&lt;/code&gt; because Swift generates one automatically. Everything else looks basically the same.&lt;/p&gt;

&lt;p&gt;So why do both exist? Why not just pick one and call it a day?&lt;/p&gt;

&lt;p&gt;Because they behave completely differently in five important ways. And those five differences are not trivia — they're the reason you'll choose one over the other throughout your entire career as an iOS developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Five Ways Classes Are Different From Structs
&lt;/h2&gt;

&lt;p&gt;Let me walk through them one by one, because each one matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Classes Don't Get a Free Initializer
&lt;/h3&gt;

&lt;p&gt;Remember how structs automatically generate a memberwise initializer? You define the properties and Swift quietly creates &lt;code&gt;AnimeCharacter(name:powerLevel:)&lt;/code&gt; for you — no extra work required.&lt;/p&gt;

&lt;p&gt;Classes don't get that.&lt;/p&gt;

&lt;p&gt;With a class, you write the initializer yourself. Every time. Which at first sounds annoying, but there's a very good reason for it — and it connects to the next point.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Classes Can Inherit From Other Classes
&lt;/h3&gt;

&lt;p&gt;This is the big one. The headline feature. The thing that makes classes genuinely different from structs rather than just structurally similar.&lt;/p&gt;

&lt;p&gt;Inheritance means one class can be built on top of another class, automatically getting all its properties and methods as a starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;village&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;introduce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; from &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Hokage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;village&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;announce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;, leader of &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;village&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Hokage&lt;/code&gt; inherits everything from &lt;code&gt;Ninja&lt;/code&gt; — &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;village&lt;/code&gt;, and &lt;code&gt;introduce()&lt;/code&gt; — and adds its own stuff on top. You can create a &lt;code&gt;Hokage&lt;/code&gt; and call &lt;code&gt;introduce()&lt;/code&gt; on it even though &lt;code&gt;Hokage&lt;/code&gt; never defined that method itself.&lt;/p&gt;

&lt;p&gt;This is why classes don't get a free initializer. If they did, and you later added a property to &lt;code&gt;Ninja&lt;/code&gt;, every &lt;code&gt;Hokage&lt;/code&gt; initializer would silently break. Swift decided it's better to make you write your own, so you're always fully aware of what your initializer is doing and what it affects.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Copies of Classes Share the Same Data
&lt;/h3&gt;

&lt;p&gt;This is the one that surprises people most, and it's genuinely important for understanding how SwiftUI works.&lt;/p&gt;

&lt;p&gt;With a struct, every copy is independent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacterStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;naruto&lt;/span&gt;
&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// 9000 — unchanged&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 9001 — only this one changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a class, copies point to the same underlying data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacterClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;naruto2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;naruto&lt;/span&gt;
&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// 9001 — ALSO changed!&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;naruto2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 9001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;naruto&lt;/code&gt; and &lt;code&gt;naruto2&lt;/code&gt; aren't two separate characters — they're two names for the same character. Change one, you change both.&lt;/p&gt;

&lt;p&gt;This sounds alarming, but it's actually exactly what you want for shared state in an app. If a user updates their profile name on one screen, you want every other screen showing that name to update automatically — not to be stuck showing the old version from their own private copy. Classes make that kind of shared, synchronized data easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Classes Have Deinitializers
&lt;/h3&gt;

&lt;p&gt;When the very last reference to a class instance goes away, Swift can run a special function called a &lt;strong&gt;deinitializer&lt;/strong&gt; — written as &lt;code&gt;deinit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;NinjaSchool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; opened!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;deinit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; closed forever."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structs don't have this because each copy of a struct is independent — there's no "last copy" to track. Classes have it because when multiple things point to the same instance, Swift needs to know when truly nobody is using it anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. You Can Change Properties on a Constant Class
&lt;/h3&gt;

&lt;p&gt;This one is subtle but important. With structs, a constant instance means nothing can change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacterStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ❌ can't change — it's a let&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With classes, a constant instance just means you can't point it at a different instance — but the data inside can still change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;naruto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacterClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Naruto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;naruto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;powerLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt; &lt;span class="c1"&gt;// ✅ this is fine!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;let naruto&lt;/code&gt; means "naruto always refers to this specific character." It doesn't mean "this character's properties can never change."&lt;/p&gt;




&lt;h2&gt;
  
  
  So When Do You Use a Class vs a Struct?
&lt;/h2&gt;

&lt;p&gt;Most Swift developers default to structs. They're simpler, safer (because copies are independent), and Swift's standard library is built almost entirely on structs.&lt;/p&gt;

&lt;p&gt;You reach for a class when you specifically want one of those five behaviors — most often the shared data one. In SwiftUI, your UI components are structs, but your data models that need to be shared across multiple views are classes. That's the pattern you'll see again and again as you build real apps.&lt;/p&gt;

&lt;p&gt;The short version:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use a Struct when...&lt;/th&gt;
&lt;th&gt;Use a Class when...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Each copy should be independent&lt;/td&gt;
&lt;td&gt;Multiple things should share the same data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want the free memberwise initializer&lt;/td&gt;
&lt;td&gt;You need inheritance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You're building UI in SwiftUI&lt;/td&gt;
&lt;td&gt;You're building data models in SwiftUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple, contained data&lt;/td&gt;
&lt;td&gt;Data that needs to be observed and shared&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The One Thing To Hold Onto
&lt;/h2&gt;

&lt;p&gt;If everything above felt like a lot — and honestly, it is a lot for one sitting — the single most important thing to remember is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structs give every copy its own data. Classes make all copies share the same data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything else about classes (inheritance, deinit, constant mutability) flows from that fundamental difference. Once that clicks, the rest starts to make sense.&lt;/p&gt;

&lt;p&gt;We'll go deeper on inheritance, deinitializers, and how all of this connects to SwiftUI in the next few articles. For now, just sit with the idea that structs and classes aren't interchangeable — they're different tools for different jobs, and knowing which one to reach for is one of the most important instincts you'll build as a Swift developer. 🌸&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>swift</category>
      <category>ios</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>I Deleted 200 Lines of Code I Didn't Write and Learned More Than When I Wrote It...</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Thu, 09 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/i-deleted-200-lines-of-code-i-didnt-write-and-learned-more-than-when-i-wrote-it-18dd</link>
      <guid>https://dev.to/gamya_m/i-deleted-200-lines-of-code-i-didnt-write-and-learned-more-than-when-i-wrote-it-18dd</guid>
      <description>&lt;p&gt;&lt;em&gt;Quick note before we dive in — I know I've been off track from the iOS/Swift series lately. I just have so many thoughts I need to get out of my head first. The series is coming back with the next article, I promise. Okay. Now. Story time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was thinking to tell you all about the afternoon I spent deleting code and accidentally learned more than I had in the entire month I spent generating it.&lt;/p&gt;

&lt;p&gt;This is not the story I expected to be telling. I went in thinking I was doing a quick cleanup. I came out a different person. Slightly humbled, deeply caffeinated, and with 200 fewer lines of Swift in a file that somehow works better now. Let me explain.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part Where I Confess Something
&lt;/h2&gt;

&lt;p&gt;A few weeks ago I was moving fast on a project. Like, embarrassingly fast. Generate, test, accept, move on. Generate, test, accept, move on. The AI was producing stuff that compiled and did the thing I asked and I was just... letting it. Not reading carefully. Not asking questions. Just vibing my way through feature after feature like someone who is definitely not going to regret this later.&lt;/p&gt;

&lt;p&gt;Reader, I regretted it later.&lt;/p&gt;

&lt;p&gt;Not because it broke. That's the genuinely annoying part — the code was fine. It ran. The features worked. Nobody was complaining. But every time I opened that file I got this low-level anxiety I couldn't quite name, like walking into a room you cleaned by shoving everything into the closet. Technically tidy. Spiritually wrong.&lt;/p&gt;

&lt;p&gt;So one afternoon I just... started deleting things. No plan. Just me, a delete key, and a growing sense that I had accepted a lot of code I did not actually understand.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Thing That Happened Was I Got Scared
&lt;/h2&gt;

&lt;p&gt;This surprised me. I'm not easily scared by code. But I kept hovering over things going "okay but what if this is the thing holding everything together and I just don't know it yet."&lt;/p&gt;

&lt;p&gt;That feeling? That is the exact feeling I never have when I write code myself. When you write something, you carry the map in your head. You remember the night you added that defensive nil check because something exploded in testing. You remember why the function is structured the way it is because you restructured it twice. You have context.&lt;/p&gt;

&lt;p&gt;With generated code, the code arrived and the context didn't come with it. The AI made decisions — some of them genuinely good decisions — and I accepted them without understanding &lt;em&gt;why&lt;/em&gt; they were the decisions. So now I'm standing here six weeks later, looking at my own project like a stranger, trying to figure out which parts are load-bearing and which are just decoration.&lt;/p&gt;

&lt;p&gt;This is exactly as uncomfortable as it sounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  So I Started Making Predictions
&lt;/h2&gt;

&lt;p&gt;Before I deleted anything, I started asking myself: okay, if I remove this, what do I think breaks? Not what could break in theory. What do I &lt;em&gt;think&lt;/em&gt; will happen, specifically.&lt;/p&gt;

&lt;p&gt;Some of my predictions were correct and deleting the thing confirmed it was redundant. Good. Simple.&lt;/p&gt;

&lt;p&gt;Some of my predictions were wrong in interesting ways. There was a function I was absolutely certain was doing nothing useful — looked like a model just added it out of habit — and when I deleted it, a very specific edge case in a flow I'd half forgotten about quietly fell apart. Turns out the function was handling a nil that could only show up under a particular sequence of user actions I didn't immediately remember building.&lt;/p&gt;

&lt;p&gt;That function taught me something I did not know I didn't know. Which is the most annoying kind of learning, but also the most useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Final Score
&lt;/h2&gt;

&lt;p&gt;200 lines gone. Some of it was genuinely redundant — duplicated logic, defensive checks for situations that couldn't actually happen, a helper function called exactly once that could have just been one line where it was used. The kind of thing that gets added by something being thorough, not by something that knows what your specific project actually needs.&lt;/p&gt;

&lt;p&gt;Some of it I rewrote from scratch. Not because the original was wrong. Because rewriting it meant I finally &lt;em&gt;owned&lt;/em&gt; it. There's a difference between code you're managing and code you understand, and I needed to close that gap before I could trust myself to work on it properly.&lt;/p&gt;

&lt;p&gt;Some of it I kept exactly as it was. Because staring at the empty space after I tried to delete it made me realize it was doing something I actually needed, and I just hadn't been paying enough attention to appreciate it. Those were the most useful deletions of all, actually — the ones where I tried to get rid of something and the project said "no, you need that, let me show you why."&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned That I Didn't Expect to Learn
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody tells you about generating code quickly: the velocity is real but it has a price that doesn't show up on the day you shipped the feature. It shows up later. It shows up when you need to change something, or debug something weird, or explain the thing to someone else, or just open the file six weeks later and feel that closet-full-of-junk anxiety.&lt;/p&gt;

&lt;p&gt;Every line you accept without understanding is a small loan. The interest compounds quietly until you need to touch the thing again.&lt;/p&gt;

&lt;p&gt;Deleting code — actually reading it carefully enough to have an opinion about whether it should exist — is one of the weirdest and most effective ways to pay that debt down. You can't delete something without understanding it well enough to argue for or against it. Which means by the time you're done, you've been forced to actually learn the codebase you thought you already knew.&lt;/p&gt;

&lt;p&gt;I came in for a cleanup. I got an education. Slightly against my will, but still.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part Where I Tell You What I'm Actually Doing Differently Now
&lt;/h2&gt;

&lt;p&gt;I haven't stopped using AI to generate code. That would be a dramatic overreaction and also I have deadlines. But I've started treating accepted suggestions like debt I'm choosing to take on, not like code I wrote. Because the moment I need to touch it again, I need to understand it — and if I never read it carefully, that understanding isn't there just because I was in the room when it was generated.&lt;/p&gt;

&lt;p&gt;So now, every once in a while, I open a file I generated fast and haven't looked at closely since. I read it like it's someone else's code. I try to delete things. I make predictions about what I think will break, and then I see if I'm right.&lt;/p&gt;

&lt;p&gt;Sometimes I am. Sometimes I'm wrong in exactly the ways that teach me something.&lt;/p&gt;

&lt;p&gt;Either way, I come out knowing the codebase better than I did going in.&lt;/p&gt;

&lt;p&gt;Which is, genuinely, more than I can say for the afternoon I generated it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI tools were used to help with grammar and structure.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>programming</category>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>I Started Writing My Prediction Before Reading the AI's Answer. Here's What Happened.</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Wed, 08 Jul 2026 03:58:48 +0000</pubDate>
      <link>https://dev.to/gamya_m/i-started-writing-my-prediction-before-reading-the-ais-answer-heres-what-happened-9c5</link>
      <guid>https://dev.to/gamya_m/i-started-writing-my-prediction-before-reading-the-ais-answer-heres-what-happened-9c5</guid>
      <description>&lt;p&gt;So a few days ago I was in a comment thread arguing about whether AI is quietly ruining junior developers' ability to develop actual judgment, and someone dropped a phrase that's been rattling around in my skull ever since: predict-then-diff.&lt;/p&gt;

&lt;p&gt;The idea, roughly: before you even look at what the AI generated, you write down what you &lt;em&gt;expect&lt;/em&gt; it to look like. Then you compare your prediction against the actual output. The gap between the two is the lesson. It's basically forcing yourself to have a hypothesis before you're allowed to see the answer, instead of just reading the answer and nodding along like it's gospel.&lt;/p&gt;

&lt;p&gt;I decided to actually try it for a week instead of just intellectually agreeing with it in a comment section like a coward. Here's what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day One: Immediate, Mild Suffering
&lt;/h2&gt;

&lt;p&gt;First task, I needed a function to paginate through a list in SwiftUI. Normally I'd just prompt it and glance at the output, mentally file it under "looks fine," and move on with my day like a functioning member of society.&lt;/p&gt;

&lt;p&gt;Instead, I sat there and actually wrote out what I expected: probably some kind of &lt;code&gt;LazyVStack&lt;/code&gt;, maybe an &lt;code&gt;onAppear&lt;/code&gt; trigger near the bottom of the list to load more, some state variable tracking the current page.&lt;/p&gt;

&lt;p&gt;Then I looked at the actual output. It used &lt;code&gt;.task&lt;/code&gt; instead of &lt;code&gt;onAppear&lt;/code&gt;, which, fine, reasonable, slightly more modern. But it also introduced a &lt;code&gt;Task.detached&lt;/code&gt; I did not predict, was not expecting, and did not understand the reasoning behind at all.&lt;/p&gt;

&lt;p&gt;And this is the part nobody warns you about: the gap didn't feel satisfying. It felt like being wrong on a pop quiz. My brain, used to just accepting whatever compiled, was mildly betrayed by being asked to have an opinion first.&lt;/p&gt;

&lt;p&gt;Immediately understood why nobody does this voluntarily. It's uncomfortable in a very specific, very unfamiliar way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day Three: The Frieren Moment
&lt;/h2&gt;

&lt;p&gt;Okay hear me out. There's this bit in Frieren where she's spent so long assuming magic works one specific way, based on centuries of pattern, that she genuinely doesn't notice when something breaks the pattern right in front of her, because she stopped predicting and started just recognizing shapes.&lt;/p&gt;

&lt;p&gt;That's what "just reading the diff and moving on" had quietly turned me into. I wasn't evaluating AI output anymore. I was pattern-matching "looks like code I've seen before" and calling that comprehension. Predict-then-diff was the first thing in months that actually made me stop and go "wait, do I actually know why this works, or do I just recognize the shape of it."&lt;/p&gt;

&lt;p&gt;Turns out, for a genuinely humbling number of things, it was the second one.&lt;/p&gt;

&lt;p&gt;By day three I caught myself predicting a force-unwrap in a spot where the AI instead used a guard clause with a proper early return. My prediction was the worse code. The gap taught me something real, and it wasn't even about the AI being smart — it was about me finally noticing my own instinct was rustier than I thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day Five: When the Method Actually Paid Off
&lt;/h2&gt;

&lt;p&gt;Here's the one that made the whole experiment worth it. I was reviewing some networking code, predicted the error handling would use a simple do-catch with a generic error message, standard stuff. The actual output silently swallowed a specific network timeout case and returned a cached value instead, with zero comment explaining why.&lt;/p&gt;

&lt;p&gt;If I'd just read it top to bottom without predicting first, I'm being honest with myself, I probably would've accepted it. It compiled. It looked plausible. Looked exactly like the kind of "smart caching fallback" pattern I've seen in real code before.&lt;/p&gt;

&lt;p&gt;But because I'd already committed to a prediction that didn't include silent fallback behavior, the gap actually stopped me. I asked why. Turned out the fallback was masking an actual bug in how the timeout was being detected upstream. Would've shipped a caching bug pretending to be a feature. The prediction is what made me suspicious enough to dig, instead of just vibing my way past it.&lt;/p&gt;

&lt;p&gt;That's the whole argument for this technique in one story, honestly. The catch didn't come from being smarter than the AI. It came from having a committed hypothesis on record that the actual output failed to match.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Think Now
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend this is sustainable for every single line of code, every single day, forever. Some things are genuinely trivial and predicting them first is just theater. Nobody needs to write down their hypothesis for a getter.&lt;/p&gt;

&lt;p&gt;But for anything with actual logic, anything where a wrong call could compound into a real bug later, I think the method is legitimately doing what it claims: it's relocating the reps. It's manufacturing the exact moment of "wait, is this actually right" that used to only show up naturally after you'd already been burned by your own mistake in production. Except now it shows up before shipping, on purpose, for free, if you're willing to sit in the mildly annoying feeling of being wrong on a pop quiz a few times a week.&lt;/p&gt;

&lt;p&gt;The posture really is the whole thing. Reading a diff and nodding treats the output as an answer. Predicting first treats it as a hypothesis you're allowed to be wrong about. Only one of those postures actually builds anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;p&gt;Has anyone else actually tried something like this, on purpose, instead of just agreeing it's a good idea in the comments and never doing it? Did it stick for you, or did you quietly drop it after day two like every other good habit I've ever attempted?&lt;/p&gt;

&lt;p&gt;And be honest: last time you accepted AI-generated code, did you have any prediction at all going in, or did you just read it once and go "yeah that tracks"?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclaimer: This article was written based on my own experiences and opinions. AI tools were used to help with grammar and structure, but the story, ideas, and voice are entirely my own.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>discuss</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Happens When Everyone Can Build Apps But Nobody Understands Them?</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Mon, 06 Jul 2026 17:03:56 +0000</pubDate>
      <link>https://dev.to/gamya_m/what-happens-when-everyone-can-build-apps-but-nobody-understands-them-5aa6</link>
      <guid>https://dev.to/gamya_m/what-happens-when-everyone-can-build-apps-but-nobody-understands-them-5aa6</guid>
      <description>&lt;p&gt;Alright, real talk moment. Last week I watched someone with zero coding background build a fully functional app in an afternoon. Working auth, a database, a halfway decent UI. Prompt in, app out. They were thrilled. I was thrilled for them. And also, if I'm honest, quietly having a small existential crisis in the corner of the room.&lt;/p&gt;

&lt;p&gt;Not because I felt threatened exactly. More like — I spent actual years learning why &lt;code&gt;guard let&lt;/code&gt; exists, why force-unwrapping an optional is basically playing production Russian roulette, why you don't just slap &lt;code&gt;@State&lt;/code&gt; on everything and hope. And now that entire chunk of hard-won suffering can apparently be skipped with a well-worded prompt and a bit of patience. Cool. Cool cool cool. Love that for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Skill Isn't Coding. It's Knowing What You Don't Know.
&lt;/h2&gt;

&lt;p&gt;Here's the thing that's been sitting weird with me: the app that person built &lt;em&gt;works&lt;/em&gt;. It runs. It does the thing. But if it breaks in a weird edge case at 2am, they have no idea why, because they never had to build the mental model that would let them find out. They have the output without the map.&lt;/p&gt;

&lt;p&gt;It's giving major "I summoned a shadow clone but I don't actually know ninjutsu" vibes. The clone can absolutely fight for you. It looks exactly like you. It even talks like you. But the second something goes wrong that the clone wasn't built to handle, you're standing there with zero chakra and zero idea what just happened, because you never did the training that would let you improvise.&lt;/p&gt;

&lt;p&gt;That's the real shift, I think. It's not "can you build the thing." It's "when the thing inevitably breaks in a way nobody predicted, do you have literally any framework for figuring out why." AI is extremely good at producing working code. It is much less good at producing a person who understands &lt;em&gt;why&lt;/em&gt; it's working, which is a completely different skill that doesn't transfer just because you were in the room when it happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Part Nobody Wants to Say Out Loud
&lt;/h2&gt;

&lt;p&gt;Here's where it gets messier though, and I want to be fair about this instead of just being smug about my years of suffering like it was some kind of noble sacrifice.&lt;/p&gt;

&lt;p&gt;A huge amount of what "understanding code" used to gatekeep wasn't actually that valuable in itself. Knowing the exact syntax for a &lt;code&gt;for&lt;/code&gt; loop in three different languages was never the point — it was a costly proxy for the thing that actually mattered, which was being able to reason about logic and structure. If AI genuinely lets more people skip the costly proxy and get straight to building useful things, that's not automatically bad. Loads of us gatekept a skill that was mostly just "memorized enough incantations to get the compiler to stop yelling," and dressed it up as deep expertise.&lt;/p&gt;

&lt;p&gt;So I don't think the honest question is "is it bad that people can build without understanding." I think it's "what happens to the people who &lt;em&gt;only&lt;/em&gt; ever build without understanding, the moment something needs actual understanding to fix." Those are very different problems, and I think a lot of the online discourse conveniently blurs them together because "everyone's fine, don't worry about it" and "everyone's cooked, we're all doomed" are both easier takes than the actually annoying, nuanced middle one.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Honest, Slightly Nervous Take
&lt;/h2&gt;

&lt;p&gt;I think we're heading toward two very different kinds of app-builders, and the split isn't going to be "used AI" vs "didn't use AI," because basically everyone's going to use it. The split is going to be between people who used AI as a &lt;em&gt;shortcut through&lt;/em&gt; understanding, versus people who used it as a &lt;em&gt;scaffold toward&lt;/em&gt; understanding — same tool, completely different relationship to it.&lt;/p&gt;

&lt;p&gt;The scaffold group asks why, even when the thing already works. They read the generated code like it's a stranger's PR, not a magic box. They break things on purpose in a sandbox just to see what the error actually looks like, so next time it happens for real they're not starting from zero. The shortcut group ships the working thing and moves on, and I get it, deadlines are real, but eventually the bill comes due, usually at the worst possible time, usually in production, usually on a Friday.&lt;/p&gt;

&lt;p&gt;I want to be in the scaffold group. Some days I actually am. Other days I catch myself accepting a suggestion because it compiled and I had somewhere to be, and I have to go back later and actually sit with what it did, like eating my vegetables after I already had the dessert.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, Your Turn, Don't Leave Me Hanging Here
&lt;/h2&gt;

&lt;p&gt;So genuinely — where do you land on this? Do you think "understanding the code" is going to matter less over time, the same way most of us don't understand assembly anymore and it's completely fine? Or is this different, because the failure modes of AI-generated logic are weirder and less predictable than the failure modes of a compiler?&lt;/p&gt;

&lt;p&gt;And be honest: when's the last time you accepted a suggestion, watched it work, and never actually went back to ask why?&lt;/p&gt;

&lt;p&gt;Asking for a friend. The friend is, once again, me. I contain multitudes and also several unexamined, accepted suggestions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written based on my own experiences and opinions. AI tools were used to help with grammar and structure, but the story, ideas, and voice are entirely my own.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>developers</category>
      <category>coding</category>
    </item>
    <item>
      <title>Who Else Has Inherited a Codebase With Zero Comments and a Prayer?</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Sun, 05 Jul 2026 13:23:33 +0000</pubDate>
      <link>https://dev.to/gamya_m/who-else-has-inherited-a-codebase-with-zero-comments-and-a-prayer-84h</link>
      <guid>https://dev.to/gamya_m/who-else-has-inherited-a-codebase-with-zero-comments-and-a-prayer-84h</guid>
      <description>&lt;p&gt;Okay so. Story time. Grab a coffee; this one's got a body count.&lt;/p&gt;

&lt;p&gt;A few months back I got assigned a "small fix" on a payment reconciliation service. Small fix. That's what the ticket said. I need that on record before I tell you what happened next, because I want you to fully feel how personally I take that betrayal.&lt;/p&gt;

&lt;p&gt;First file I open has a function called &lt;code&gt;handlePayment2&lt;/code&gt;. Not &lt;code&gt;handlePaymentV2&lt;/code&gt;. Not &lt;code&gt;handlePaymentUpdated&lt;/code&gt;. Just &lt;code&gt;2&lt;/code&gt;. Like someone typed it out, looked at it, and thought, "Yeah, that's a professional software artifact," and then went to lunch. And it's sitting right next to &lt;code&gt;handlePayment&lt;/code&gt;, which is STILL being called in three other places. Nobody deleted the original. It's just there. Both of them. Living together. Co-parenting the payment flow like a divorced couple who still share a group chat.&lt;/p&gt;

&lt;p&gt;Zero comments anywhere in the file. Not one. I scrolled 400 lines and found exactly one piece of human text in the whole thing: &lt;code&gt;// TODO fix this&lt;/code&gt;, dated 2022. Fix &lt;em&gt;what&lt;/em&gt;. FIX WHAT, my guy. That's not a comment, that's a cry for help mailed to nobody.&lt;/p&gt;

&lt;p&gt;This is when I realized the whole ordeal was giving me full Death Note energy — except instead of L calmly deducing a serial killer's identity from crumbs of evidence, it was just me, at 11pm, trying to deduce why a boolean exists using nothing but vibes and rage.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Investigation Begins (Send Help)
&lt;/h2&gt;

&lt;p&gt;Naturally I did the thing we all do when betrayed by silence: I opened &lt;code&gt;git blame&lt;/code&gt; like it owed me money.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git blame&lt;/code&gt; on a codebase like this is a treasure map where X marks the spot, except the X is a commit from a user called &lt;code&gt;temp-fix-do-not-merge&lt;/code&gt; who does not exist anymore, possibly never existed, possibly ascended. The treasure itself was a config flag called &lt;code&gt;useNewLogic&lt;/code&gt;, which — plot twist — is neither new, nor optional, nor logic anyone currently understands. I spent two hours confirming the "old" path had been fully dead since 2023. Nobody deleted it. It's just sitting there, radioactive, feared by all, touched by none.&lt;/p&gt;

&lt;p&gt;Big Frieren energy, honestly. A thousand-year-old elf mage carrying memories nobody else is even alive to share anymore. That's &lt;code&gt;useNewLogic&lt;/code&gt;. It has seen wars. It remembers the Great Migration of 2023 that literally no one currently employed was present for.&lt;/p&gt;

&lt;p&gt;The commit messages offered zero comfort. Real messages, paraphrased slightly so I don't doxx my former coworkers: "fix bug." "update per request." "changes." And then one, glorious, unhinged entry that just said: "idk." Lowercase. No period. A confession dressed up as documentation.&lt;/p&gt;

&lt;p&gt;You inherit the code. You do not inherit the two Slack threads and one hallway conversation where the actual reasoning lived and died. That context left the building the day the original dev did, and there is no jutsu, no summoning scroll, no Dragon Ball wish that brings it back. I checked. I would not lie to you about something this important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Happens to Literally Everyone, Not Just Cursed People
&lt;/h2&gt;

&lt;p&gt;I used to think uncommented codebases were a "lazy dev" problem. Wrong. I've met genuinely sharp, careful engineers who still leave behind absolute crime scenes, because it was never about laziness. It's about:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The deadline was real, the comment was not.&lt;/strong&gt; Three hours before launch, nobody's thinking "how will this read to a confused stranger in 2026." They're thinking "please, for the love of god, just work." Comments die first in every crunch, on every team, in every universe including several I haven't worked on yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It felt obvious while you were inside it.&lt;/strong&gt; The sneakiest one. Deep in a problem, your brain holds the whole context loaded, so everything looks self-explanatory — right up until that context evaporates and future-you is left staring at your own code like it's written in a language you almost speak.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody ever got promoted for a great docstring.&lt;/strong&gt; Ship the feature, get the Slack praise emoji. Explain the tradeoff clearly for whoever comes next? Silence. Not even future-you says thank you, and future-you is the one who needed it most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deleting dead code takes more nerve than writing new code.&lt;/strong&gt; &lt;code&gt;handlePayment2&lt;/code&gt; exists because deleting &lt;code&gt;handlePayment&lt;/code&gt; means someone has to be SURE, professionally, put-your-name-on-the-commit sure, that nothing depends on it. Way easier to slap a &lt;code&gt;2&lt;/code&gt; on it and back away slowly. I say this with love: I have also been the guy who added the &lt;code&gt;2&lt;/code&gt;. We contain multitudes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Changed For Me After This
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend I became a documentation monk overnight, glowing with the wisdom of a thousand clean commits. But a few things genuinely stuck:&lt;/p&gt;

&lt;p&gt;I started writing down the archaeology &lt;em&gt;as I did it&lt;/em&gt;, not after, because "after" never comes. The second I confirmed something was dead, I left a comment saying so — confirmed dead as of this date, verified via logs, here's exactly how. Whoever comes next doesn't have to redo my two hours of suffering. Let my pain be their shortcut.&lt;/p&gt;

&lt;p&gt;I stopped refactoring and understanding at the same time, because that's how you delete the one line holding the entire building up. Understand first, in a throwaway branch. Refactor second, once you actually know what's load-bearing and what's decorative.&lt;/p&gt;

&lt;p&gt;I started assuming every "temporary" fix is permanent, because it always, always is. If it's survived longer than a sprint, it has tenure now. Respect the tenure.&lt;/p&gt;

&lt;p&gt;And weirdly, I got a lot more sympathetic to whoever wrote the original mess. They weren't careless — they were a person, under a deadline, doing their best with the time they had. Same as me right now, quietly leaving behind my own future crime scene for someone else to &lt;code&gt;git blame&lt;/code&gt; in 2027.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Turn, Don't Be Shy
&lt;/h2&gt;

&lt;p&gt;I refuse to believe I'm the only one with a story like this. So:&lt;/p&gt;

&lt;p&gt;What's the worst codebase you've ever inherited? What's the most deranged commit message you've personally witnessed with your own two eyes? And — deep breath — if a stranger opened your code from a year ago right now, zero context, cold read, would they curse your name, or would you actually be fine?&lt;/p&gt;

&lt;p&gt;Asking for a friend. The friend is me. I already know the answer and I am choosing to grow from it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was written based on my own experiences and opinions. AI tools were used to help with grammar and structure, but the story, ideas, and voice are entirely my own.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>discuss</category>
      <category>programming</category>
      <category>career</category>
      <category>development</category>
    </item>
    <item>
      <title>Swift Structs — Static Properties and Methods 🏛️</title>
      <dc:creator>Gamya </dc:creator>
      <pubDate>Sat, 04 Jul 2026 08:44:00 +0000</pubDate>
      <link>https://dev.to/gamya_m/swift-structs-static-properties-and-methods-427c</link>
      <guid>https://dev.to/gamya_m/swift-structs-static-properties-and-methods-427c</guid>
      <description>&lt;p&gt;Sometimes you want data or functionality to belong to a struct itself, not to any individual instance. That's what static properties and methods are for—let's break them down with some examples!&lt;/p&gt;

&lt;p&gt;Every property and method we've added to our structs so far has belonged to &lt;em&gt;instances&lt;/em&gt; — each &lt;code&gt;Ninja&lt;/code&gt; you create has its own &lt;code&gt;name&lt;/code&gt;, each &lt;code&gt;Guild&lt;/code&gt; has its own &lt;code&gt;gold&lt;/code&gt;. But sometimes you need data or functionality that belongs to the &lt;em&gt;struct itself&lt;/em&gt;, shared across everything. That's where &lt;code&gt;static&lt;/code&gt; comes in. 🍥&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Static Solves
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an anime series tracker app and we want to keep a count of how many series have been registered — not on any one series, but across &lt;em&gt;all&lt;/em&gt; of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeSeries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;totalRegistered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"String) {"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; has been added to the tracker!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;totalRegistered&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;static&lt;/code&gt; keyword on both the property and the method. This means they belong to &lt;code&gt;AnimeSeries&lt;/code&gt; the &lt;em&gt;type&lt;/em&gt; itself — not to any specific instance.&lt;/p&gt;

&lt;p&gt;Here's how you use them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;AnimeSeries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Naruto&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;
&lt;span class="kt"&gt;AnimeSeries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;One Piece&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;
&lt;span class="kt"&gt;AnimeSeries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Attack on Titan&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AnimeSeries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;totalRegistered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No instance needed — you call directly on &lt;code&gt;AnimeSeries&lt;/code&gt;. That's the key difference: regular properties need an instance (&lt;code&gt;var series = AnimeSeries()&lt;/code&gt;), static properties belong to the struct itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why No &lt;code&gt;mutating&lt;/code&gt; Keyword?
&lt;/h2&gt;

&lt;p&gt;You might have noticed that &lt;code&gt;register()&lt;/code&gt; modifies &lt;code&gt;totalRegistered&lt;/code&gt; but isn't marked as &lt;code&gt;mutating&lt;/code&gt;. That's because &lt;code&gt;mutating&lt;/code&gt; is only needed for regular instance methods, to handle cases where the struct instance was created as a constant.&lt;/p&gt;

&lt;p&gt;Static properties and methods don't belong to any instance, so there's no instance to be constant or variable — &lt;code&gt;mutating&lt;/code&gt; simply doesn't apply here.&lt;/p&gt;




&lt;h2&gt;
  
  
  self vs Self — Two Different Things
&lt;/h2&gt;

&lt;p&gt;Now that we have static members, there are two similar-looking keywords that mean very different things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;self&lt;/code&gt;&lt;/strong&gt; (lowercase) — refers to the &lt;em&gt;current instance&lt;/em&gt; of the struct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Self&lt;/code&gt;&lt;/strong&gt; (uppercase) — refers to the &lt;em&gt;current type&lt;/em&gt; itself
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;Ninja&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;introduce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// self = this specific ninja&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"We are all &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;s"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Self = the Ninja type&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A helpful way to remember: Swift types always start with a capital letter (&lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Bool&lt;/code&gt;) — and &lt;code&gt;Self&lt;/code&gt; follows that same convention because it &lt;em&gt;is&lt;/em&gt; a type.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two Main Uses for Static
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use 1 — Storing Shared App Data
&lt;/h3&gt;

&lt;p&gt;Static properties are perfect for storing data that's the same everywhere in your app — configuration, constants, shared settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AppConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;appVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0.0"&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;maxEpisodesPerDay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;animeAPIBaseURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.animelist.com"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now anywhere in your app you need the version number or API URL, you just write &lt;code&gt;AppConfig.appVersion&lt;/code&gt; or &lt;code&gt;AppConfig.animeAPIBaseURL&lt;/code&gt;. No need to create an instance — you just read it directly from the type.&lt;/p&gt;

&lt;p&gt;This is cleaner and safer than defining these as loose global constants floating around your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use 2 — Example Instances for SwiftUI Previews
&lt;/h3&gt;

&lt;p&gt;This one is especially useful in SwiftUI. When you're building a screen that displays a &lt;code&gt;Ninja&lt;/code&gt; or an &lt;code&gt;AnimeCharacter&lt;/code&gt;, SwiftUI lets you preview it in Xcode — but you need some sample data to fill it with.&lt;/p&gt;

&lt;p&gt;The cleanest way to provide that is with a &lt;code&gt;static let example&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AnimeCharacter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Goku"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Dragon Ball Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;powerLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9001&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whenever you need a sample character to pass into a SwiftUI preview, you just write &lt;code&gt;AnimeCharacter.example&lt;/code&gt;. It's always available, always consistent, and you didn't need to create a new instance just to test your UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mixing Static and Non-Static
&lt;/h2&gt;

&lt;p&gt;You can have both static and regular members in the same struct — but there are rules about how they interact:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From static code, you can't access non-static members:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeSeries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;totalRegistered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;showTitle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Can't access — which instance's title would this be?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes sense: if you're in static code, there's no specific instance to read from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From non-static code, you can access static members using the type name:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeSeries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;totalRegistered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; — Series #&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="kt"&gt;AnimeSeries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;totalRegistered&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Combining Static with Private
&lt;/h2&gt;

&lt;p&gt;You can also combine &lt;code&gt;static&lt;/code&gt; with access control from the last article. For example, if you want a counter that's shared across all instances but can only be changed through a controlled method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;AnimeEpisodeTracker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;episodesWatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;episodesWatched&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Episodes watched today: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;episodesWatched&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;totalWatched&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;episodesWatched&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;AnimeEpisodeTracker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// "Episodes watched today: 1"&lt;/span&gt;
&lt;span class="kt"&gt;AnimeEpisodeTracker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// "Episodes watched today: 2"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AnimeEpisodeTracker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;totalWatched&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// AnimeEpisodeTracker.episodesWatched // ❌ private — not accessible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;episodesWatched&lt;/code&gt; counter is shared across the entire app, but it's &lt;code&gt;private&lt;/code&gt; so it can only be changed through &lt;code&gt;watch()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Note on When to Use Static
&lt;/h2&gt;

&lt;p&gt;Static properties and methods aren't something you'll reach for constantly — most of the time, regular instance properties and methods are what you need. But they shine in a handful of situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App-wide constants&lt;/strong&gt; — version numbers, API endpoints, configuration values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared counters or state&lt;/strong&gt; — something that tracks across all instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SwiftUI preview data&lt;/strong&gt; — &lt;code&gt;static let example&lt;/code&gt; for sample instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utility methods&lt;/strong&gt; — helper functions that don't need any instance data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;static&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Belongs to the struct type itself, not to any instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static property&lt;/td&gt;
&lt;td&gt;Shared across all instances — accessed via the type name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Static method&lt;/td&gt;
&lt;td&gt;Called on the type directly, no instance needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Self&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common uses&lt;/td&gt;
&lt;td&gt;Shared app data, SwiftUI preview examples, utility methods&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;em&gt;This article was written by me; AI was used to improve grammar and readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>beginners</category>
      <category>ios</category>
      <category>swift</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
