<?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: MN IN</title>
    <description>The latest articles on DEV Community by MN IN (@mn_in_4951c0dbf0f61a57b50).</description>
    <link>https://dev.to/mn_in_4951c0dbf0f61a57b50</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%2F3901532%2Fa4124ecd-bc5b-42e5-9ac6-27f38ad139af.jpg</url>
      <title>DEV Community: MN IN</title>
      <link>https://dev.to/mn_in_4951c0dbf0f61a57b50</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mn_in_4951c0dbf0f61a57b50"/>
    <language>en</language>
    <item>
      <title>Building MoonSound: a SwiftUI desk clock with audio, widgets, Live Activities and iCloud sync</title>
      <dc:creator>MN IN</dc:creator>
      <pubDate>Wed, 06 May 2026 08:43:26 +0000</pubDate>
      <link>https://dev.to/mn_in_4951c0dbf0f61a57b50/building-moonsound-a-swiftui-desk-clock-with-audio-widgets-live-activities-and-icloud-sync-452o</link>
      <guid>https://dev.to/mn_in_4951c0dbf0f61a57b50/building-moonsound-a-swiftui-desk-clock-with-audio-widgets-live-activities-and-icloud-sync-452o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj2066ufh2hu7skziqsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj2066ufh2hu7skziqsu.png" alt=" " width="800" height="479"&gt;&lt;/a&gt;&lt;br&gt;
I recently shipped MoonSound, an iOS app that combines a full-screen clock, a white-noise mixer and a Pomodoro timer.&lt;/p&gt;

&lt;p&gt;The user-facing idea is simple: turn an iPhone or iPad into a calm desk companion. The implementation ended up touching more native iOS APIs than I expected.&lt;/p&gt;

&lt;p&gt;The app is built with SwiftUI and an MVVM structure. The main screens are intentionally immersive: clock, focus and sounds live in a paging container, while the navigation controls auto-hide so the device can sit on a desk without feeling like an app screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8i6tp2vrskchd2ezi8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8i6tp2vrskchd2ezi8z.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some implementation details that were interesting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AVFoundation&lt;/code&gt; handles looping sound playback and background audio.&lt;/li&gt;
&lt;li&gt;Multiple sound tracks can play at once, each with independent volume.&lt;/li&gt;
&lt;li&gt;Sound categories are loaded with on-demand resources instead of putting everything in the initial app binary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ActivityKit&lt;/code&gt; powers the Lock Screen and Dynamic Island focus countdown.&lt;/li&gt;
&lt;li&gt;WidgetKit provides clock, focus and sound widgets in home-screen and Lock Screen families.&lt;/li&gt;
&lt;li&gt;App Intents expose actions like playing a mix, stopping sounds and starting focus sessions to Siri and Shortcuts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NSUbiquitousKeyValueStore&lt;/code&gt; syncs custom mixes, favorites, recents and focus history.&lt;/li&gt;
&lt;li&gt;HealthKit can write completed focus sessions as Mindful Minutes, but only after the user enables it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One design decision I liked: the focus timer can fade out the current sound mix at the end of a round, then resume it on the next round. If the user manually changes the sound, the app respects that and drops the automatic resume snapshot.&lt;/p&gt;

&lt;p&gt;MoonSound is not a complicated app from the outside, but it was a good reminder that small utilities often become better when they lean into the platform instead of trying to build everything themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9fsi9lrrttyt38oq6uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9fsi9lrrttyt38oq6uw.png" alt=" " width="800" height="479"&gt;&lt;/a&gt;&lt;br&gt;
App Store:&lt;br&gt;
&lt;a href="https://apps.apple.com/us/app/moonsound-clock-white-noise/id6761410056" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/moonsound-clock-white-noise/id6761410056&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swiftui</category>
      <category>ios</category>
      <category>productivity</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Building an iOS app blocker with Screen Time APIs</title>
      <dc:creator>MN IN</dc:creator>
      <pubDate>Tue, 28 Apr 2026 05:58:25 +0000</pubDate>
      <link>https://dev.to/mn_in_4951c0dbf0f61a57b50/building-an-ios-app-blocker-with-screen-time-apis-30dn</link>
      <guid>https://dev.to/mn_in_4951c0dbf0f61a57b50/building-an-ios-app-blocker-with-screen-time-apis-30dn</guid>
      <description>&lt;p&gt;I recently built a small iPhone app called FocusLock.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5zk6iefroba0smatipd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5zk6iefroba0smatipd.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea is simple: choose distracting apps, create a rule, and let the phone enforce the boundary when it is time to focus.&lt;/p&gt;

&lt;p&gt;I built it because I kept running into the same problem with my own phone habits. I did not need a bigger productivity system. I needed fewer tiny negotiations with myself.&lt;/p&gt;

&lt;p&gt;This post is mostly about the technical side: what it is like to build this kind of app on iOS, what Apple gives you through the Screen Time APIs, and the tradeoffs I ran into while building the first version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhnaqqfeo0az5uh46hhy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhnaqqfeo0az5uh46hhy.jpg" alt=" " width="700" height="950"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The main frameworks
&lt;/h2&gt;

&lt;p&gt;FocusLock is built around a few Apple frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FamilyControls&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ManagedSettings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DeviceActivity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UserNotifications&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SwiftUI&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a high level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FamilyControls&lt;/code&gt; lets the user choose apps or app categories through Apple's system picker.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ManagedSettings&lt;/code&gt; lets the app apply shields to the selected apps/categories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DeviceActivity&lt;/code&gt; lets the system wake an extension when a scheduled interval starts or ends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important detail is that the app never receives normal app identifiers in the way people might expect. The selections are represented as opaque tokens. That is good for privacy, but it also shapes the product design. You cannot build a traditional analytics dashboard showing exactly which apps were opened. The system intentionally keeps that information constrained.&lt;/p&gt;

&lt;p&gt;For an app like FocusLock, that is a feature, not a limitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The app / extension split
&lt;/h2&gt;

&lt;p&gt;The main app handles the normal product surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;onboarding&lt;/li&gt;
&lt;li&gt;rule creation&lt;/li&gt;
&lt;li&gt;app selection&lt;/li&gt;
&lt;li&gt;focus timer&lt;/li&gt;
&lt;li&gt;daily quota state&lt;/li&gt;
&lt;li&gt;stats&lt;/li&gt;
&lt;li&gt;settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Device Activity Monitor extension handles system-level enforcement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a scheduled interval starts&lt;/li&gt;
&lt;li&gt;the extension loads the stored app selection&lt;/li&gt;
&lt;li&gt;it applies the shield using &lt;code&gt;ManagedSettingsStore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;when the interval ends, it clears the shield&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That split is important because the main app may not be running. If the app is killed, a simple timer inside the app is not enough. Anything that has to happen reliably later needs to be represented in a way the system can execute.&lt;/p&gt;

&lt;p&gt;That was especially important for daily quotas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Schedule mode
&lt;/h2&gt;

&lt;p&gt;The simplest rule type is schedule mode.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monday to Friday&lt;/li&gt;
&lt;li&gt;9:00 AM to 6:00 PM&lt;/li&gt;
&lt;li&gt;lock selected social apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app stores the rule locally, stores the &lt;code&gt;FamilyActivitySelection&lt;/code&gt; in an App Group so the extension can read it, then registers a &lt;code&gt;DeviceActivitySchedule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the interval starts, the extension applies the shield. When the interval ends, the extension clears it.&lt;/p&gt;

&lt;p&gt;This is the cleanest model because the system owns the timing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Daily quota mode
&lt;/h2&gt;

&lt;p&gt;Daily quotas were trickier.&lt;/p&gt;

&lt;p&gt;I did not want the app to be only a hard blocker. Sometimes a full block is too rigid. A quota feels more realistic: you can still use an app intentionally, but you have to decide whether it is worth spending part of the allowance.&lt;/p&gt;

&lt;p&gt;The first version of quota mode works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The selected apps are normally shielded.&lt;/li&gt;
&lt;li&gt;The user taps "Use Now".&lt;/li&gt;
&lt;li&gt;The app clears the shield temporarily.&lt;/li&gt;
&lt;li&gt;It stores an unlock-until timestamp.&lt;/li&gt;
&lt;li&gt;It schedules a relock event.&lt;/li&gt;
&lt;li&gt;When time expires, the apps are shielded again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key lesson was that an in-memory timer is not enough. If the user swipes the app away, the relock still needs to happen.&lt;/p&gt;

&lt;p&gt;So the app also registers a short &lt;code&gt;DeviceActivitySchedule&lt;/code&gt; for the relock moment. The extension sees that event and reapplies the shield even if the main app is not alive.&lt;/p&gt;

&lt;p&gt;That is the kind of edge case that seems small until you build the feature. A quota that sometimes fails to relock is worse than no quota at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strict mode
&lt;/h2&gt;

&lt;p&gt;Strict mode is a product decision more than a technical one.&lt;/p&gt;

&lt;p&gt;Most app blockers fail at the same point: the user disables the blocker when they want the distraction most.&lt;/p&gt;

&lt;p&gt;FocusLock handles this by making active strict rules harder to edit, disable, or delete. There is still an emergency unlock, because I do not think software should trap people. But the emergency flow adds friction: wait, confirm, and make the decision explicit.&lt;/p&gt;

&lt;p&gt;That friction is the feature.&lt;/p&gt;

&lt;p&gt;I tried to avoid making it feel moralistic. The goal is not to shame the user. The goal is to give the version of you that created the rule a little more weight when the current version of you wants to break it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy constraints
&lt;/h2&gt;

&lt;p&gt;I wanted the app to be local-first.&lt;/p&gt;

&lt;p&gt;FocusLock does not use analytics SDKs, ads, tracking, or accounts. Rules and preferences are stored on device. iCloud Key-Value Storage is used so settings can survive reinstalling the app.&lt;/p&gt;

&lt;p&gt;The only network request in the app is optional: the focus timer can fetch Bing wallpapers for its background.&lt;/p&gt;

&lt;p&gt;This also made the implementation simpler. There is no backend to secure, no account system to maintain, and no analytics event taxonomy to argue about. For this category, less infrastructure felt like the right choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;A few things stood out while building this:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Reliability matters more than feature count
&lt;/h3&gt;

&lt;p&gt;If a lock does not apply at the right time, users lose trust immediately. I spent more time thinking about app lifecycle, relock behavior, and extension state than about adding more UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Opaque tokens force better privacy
&lt;/h3&gt;

&lt;p&gt;Apple's model prevents a lot of tempting product ideas. You cannot casually turn app usage into a detailed behavioral profile. That can feel restrictive, but for a focus app, it aligns with the product's values.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Friction can be humane
&lt;/h3&gt;

&lt;p&gt;Not every feature should optimize for the fewest taps. Sometimes the whole point is to slow the user down just enough to make a conscious choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The best productivity tool is often a boundary
&lt;/h3&gt;

&lt;p&gt;I have tried many planners, trackers, and task systems. They can help, but the biggest improvement for me came from removing access to distractions before I needed willpower.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current state
&lt;/h2&gt;

&lt;p&gt;The first version includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scheduled app locks&lt;/li&gt;
&lt;li&gt;daily quotas&lt;/li&gt;
&lt;li&gt;progressive quota reduction&lt;/li&gt;
&lt;li&gt;strict mode&lt;/li&gt;
&lt;li&gt;emergency unlock&lt;/li&gt;
&lt;li&gt;Pomodoro-style focus timer&lt;/li&gt;
&lt;li&gt;achievements&lt;/li&gt;
&lt;li&gt;daily and weekly reports&lt;/li&gt;
&lt;li&gt;14 languages&lt;/li&gt;
&lt;li&gt;no account, no ads, no tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is available on the App Store here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/us/app/focuslock-smart-app-lock/id6760992215" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/focuslock-smart-app-lock/id6760992215&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am still learning what makes this kind of tool useful long term. If you have built with the Screen Time APIs, or if you have strong opinions about app blockers, I would be interested in hearing what worked and what did not.&lt;/p&gt;

&lt;p&gt;The hard part is not blocking an app.&lt;/p&gt;

&lt;p&gt;The hard part is designing a boundary people will actually respect when they are tired, bored, or avoiding something difficult.&lt;/p&gt;

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