<?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: Dima Ulyanov</title>
    <description>The latest articles on DEV Community by Dima Ulyanov (@dima_ulyanov_787bd1026dae).</description>
    <link>https://dev.to/dima_ulyanov_787bd1026dae</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965197%2Fa45fcb36-397a-489e-84e5-8c85b54afecf.png</url>
      <title>DEV Community: Dima Ulyanov</title>
      <link>https://dev.to/dima_ulyanov_787bd1026dae</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dima_ulyanov_787bd1026dae"/>
    <language>en</language>
    <item>
      <title>Key point in Do List 100 v2.0 Brings Due Dates, Auto-Progress and Full iPad &amp; Mac Support</title>
      <dc:creator>Dima Ulyanov</dc:creator>
      <pubDate>Tue, 02 Jun 2026 18:47:24 +0000</pubDate>
      <link>https://dev.to/dima_ulyanov_787bd1026dae/key-point-in-do-list-100-v20-brings-due-dates-auto-progress-and-full-ipad-mac-support-1b49</link>
      <guid>https://dev.to/dima_ulyanov_787bd1026dae/key-point-in-do-list-100-v20-brings-due-dates-auto-progress-and-full-ipad-mac-support-1b49</guid>
      <description>&lt;p&gt;Hi everybody. &lt;br&gt;
We have created this app around two months and this is third version with fixed bugs. Now it is amazing app that synchronization your tasks throughs iPhone iPad Mac via iCloud with no Sign In! And in pocket you will already have a useful notes. &lt;/p&gt;

&lt;p&gt;It was a huge code work. Hours and hours. Such a pleasure.&lt;/p&gt;

&lt;p&gt;What I want to note here for you fellas, we were going from these scheme:&lt;/p&gt;

&lt;h2&gt;
  
  
  What's really happening
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The self-overwrite loop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User edits subtask title
        ↓
onChange fires → scheduleSave() → debounce 1s
        ↓
...debounce fires → DataManager.save() writes todos.json to iCloud
        ↓
NSMetadataQuery detects file change on disk
        ↓                         ↑
        └── todosChanged() ───────┘
              ↓
        taskManager.loadTodos()
              ↓
        self.todos = loadedTodos   ← 💥 replaces entire array mid-edit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core problem is that &lt;code&gt;NSMetadataQuery&lt;/code&gt; watches the file at the OS level. It has &lt;strong&gt;no concept of who made the change&lt;/strong&gt; — your own app writing the file looks identical to another device syncing a change over iCloud. So every save you make triggers a reload that cancels whatever the user is currently doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why subtask titles are worst affected
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;TextField&lt;/code&gt; bound to &lt;code&gt;$subtask.title&lt;/code&gt; is live — it reflects the array value character by character. The moment &lt;code&gt;self.todos = loadedTodos&lt;/code&gt; runs, SwiftUI throws away the in-memory array and rebuilds from the freshly decoded JSON. If the save hasn't happened yet (debounce still counting down), the loaded file has the &lt;em&gt;old&lt;/em&gt; title, and the field visually snaps back.&lt;/p&gt;

&lt;p&gt;Progress sliders have the same issue but it's less noticeable because a slider value is a &lt;code&gt;Double&lt;/code&gt; — the snap-back is a jump rather than disappearing characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it only shows up on real devices
&lt;/h3&gt;

&lt;p&gt;The simulator runs everything on the same Mac so iCloud writes are near-instant and the race window is tiny. On a real device the file system is slower and iCloud sync adds latency, making the timing gap between "user is editing" and "reload fires" much more visible.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three fixes needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fix 1 — Ignore self-triggered reloads in &lt;code&gt;DataManager&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Track a &lt;code&gt;isSavingLocally&lt;/code&gt; flag. Set it &lt;code&gt;true&lt;/code&gt; before writing, &lt;code&gt;false&lt;/code&gt; after. In &lt;code&gt;todosChanged()&lt;/code&gt; skip the reload if the flag is set. This stops your own saves from triggering reloads entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix 2 — Add an &lt;code&gt;isEditing&lt;/code&gt; guard in &lt;code&gt;TaskManager&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Expose a simple &lt;code&gt;isUserEditing: Bool&lt;/code&gt; flag that &lt;code&gt;ContentView&lt;/code&gt; sets to &lt;code&gt;true&lt;/code&gt; when a &lt;code&gt;TextField&lt;/code&gt; is focused and &lt;code&gt;false&lt;/code&gt; on &lt;code&gt;onSubmit&lt;/code&gt;/focus loss. &lt;code&gt;loadTodos()&lt;/code&gt; checks this flag and skips the reload if the user is mid-edit, queuing it for after they finish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix 3 — Debounce the reload too, not just the save&lt;/strong&gt;&lt;br&gt;
Right now saves are debounced (1 second) but reloads are instant. If a remote change does arrive legitimately, it should also wait briefly before replacing the array — giving any in-flight edits time to be committed first. A 0.5-second debounce on &lt;code&gt;todosChanged()&lt;/code&gt; is enough.&lt;/p&gt;

&lt;p&gt;TO THIS: &lt;/p&gt;

&lt;p&gt;Own save    → flag set    → reload blocked entirely&lt;br&gt;
Mid-edit    → isEditing   → reload deferred until focus lost&lt;br&gt;&lt;br&gt;
Remote sync → debounced   → reload waits 0.5s before replacing array&lt;/p&gt;

&lt;p&gt;Interesting in your opinions. &lt;/p&gt;

&lt;p&gt;[LINK TO THE APP(&lt;a href="https://apps.apple.com/us/app/do-list-100/id6758045201)" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/do-list-100/id6758045201)&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>apple</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
