Thorsten Stark

Thorsten Stark

@thostark.bsky.social

iOS Developer since 2009 – doing Swift, SwiftUI, Objc, macOS, UI/UX, CI/CD, git, automation and a bit more. Developer of @batteriesapp.bsky.social

142 followers160 following107 posts

On a school day the iPad Today screen in KidsPlaner shows today and tomorrow side by side. On weekends it used to stack a full-width notice above Monday. The notice is now a card beside Monday, so the screen keeps its shape. iPhone keeps the strip. #indiedev #swiftui

If your school holidays already sit in a calendar on your phone, KidsPlaner can import them. You pick the calendar, untick what is not a holiday, and the rest becomes holidays for that child. Calendar import is part of Pro. #backtoschool #iosdev

Write down the day you put a battery in. That date starts its clock, whatever the purchase date says. At the next swap, the time between the two dates is how long this device runs on a set. After a few swaps you can plan instead of guess. #batteries #iosdev

KidsPlaner now has a Children tab: periods, subjects, events and holidays of one child on one screen. Before, they sat in three places: a tab, Settings and a list two levels down. #indiedev #swiftui #backtoschool

A vertical bar on iPhone Duo has a fixed width, so a long text label has nowhere to grow. Items with an icon go to the vertical axis, text-only items stay horizontal. Set both a title and an image on every toolbar item and let the system pick. #iosdev #iphoneduo

On iPhone Duo an app gets vertical bars only when it rebuilds against the newest SDK and lets a navigation container own its bars. A bar built by hand from UIToolbar, UINavigationBar or UITabBar has its content ignored entirely. The system cannot tell those are bar items. #iosdev #iphoneduo

Opening Batteries At Home with zero devices shows its own screen: one illustration, one headline, one button to add your first device. Everything else in the app only makes sense once a device exists, so that empty screen gets the same design attention as the loaded one. #iosdev #swiftui

iPhone Duo moves navigation, toolbar and tab items into one vertical bar at the edge of the display. A screen that is worse off can opt out: toolbarVerticalBehavior(.disabled) in SwiftUI, preferredVerticalBarBehavior returning .disabled in UIKit. #iosdev #iphoneduo

An iOS widget runs in an extension, and that extension has a much tighter memory budget than an app. Decoding a full resolution photo in a timeline provider may get the process killed. No crash to see, just the placeholder. Downsample before you render. #iosdev #widgetkit

The hardest number in my battery tracker is the first battery in a new device. Two recorded changes in, the next one is arithmetic. A new device has no dates yet. The usual lifetime comes from the average for that battery type in the house, with an indicator for how sure it is. #indiedev #iosdev

@ Observable tracks reads per view. A view is invalidated only by the properties it read in its last body pass. ObservableObject publishes at the object level, so every observing view redraws, whatever changed. Reading a property for a debug print now subscribes you to it. #iosdev #swiftui

A subject stores one colour, and the app has two appearances. Navy reads on white and disappears on a nearly black tile. So KidsPlaner never draws the stored hex. Every rendering asks for a legible version that resolves per appearance. Not live yet. #indiedev #swiftui #backtoschool

Two parents, one timetable, and until now each of them types it in separately. The next update shares a child's schedule with a second iCloud user, read only or with editing. Sharing is Pro, accepting an invitation is not. Not live yet. #backtoschool

The next update gives KidsPlaner a school year view in two modes: compact, the whole year from August to July on one screen, and detailed, with weekdays and event names. Not live yet. #backtoschool

Actors are reentrant, and that is the part everyone misses. An actor guarantees one task touches its state at a time. It does not guarantee your function runs undisturbed. Every await is a door. Re-read state after awaiting. #iosdev #swift

The small widget in Batteries At Home used to be a list of rows. It is a 2x2 grid now. Four devices fit, each one a ring: remaining lifetime as the arc, state as the color, the device icon in the middle. Every cell is its own Link, so a tap opens that device. #indiedev #widgetkit

The Predicate macro in SwiftData is not a Swift closure. It is a query builder. Everything in it has to translate into a database query. Computed properties and helper methods do not exist down there, so you get a compile error or a fetch that fails. #iosdev #swiftdata

If two branches of an if render the same view, pass the difference as data instead. @ State is not attached to your view, it is attached to its position in the view tree. Two branches are two identities, and switching between them throws the state away. #swiftui #iosdev

A status screen needs a state for nothing to do, and that state should be the common one. The dashboard in Batteries At Home has four: first run, calm, normal, alarm. Calm means nothing overdue and nothing due within seven days, and it says so instead of ranking devices. #indiedev #swiftui

Your widget can show a live countdown without spending a single timeline reload. Text(date, style: .timer) and ProgressView(timerInterval:) are updated by the system between reloads. Everything else needs a new timeline entry, from a budget you do not control. #iosdev #widgetkit

A timetable app that only shows today answers only half the question. In the evening you want to know what's needed tomorrow: gym kit, instrument, you name it. So the Today screen in KidsPlaner shows what is now important to know. #indiedev #swiftui

`Task { }` doesn't move work off the main thread. It inherits the actor context. In SwiftUI that's @ MainActor. In Xcode 26, `nonisolated async` doesn't either: it runs on the caller's actor. Want off? Mark it `@ concurrent`.

Aaaaannndddd we are live 🎉 version 2.0 of Batteries At Home is in the App Store now. It brings a new dashboard, new design, shopping list for needed batteries and much more. #builtinpublic #ios #smarthome

Today I tried to connect to a nearby Mac from my cmux terminal via ssh. It failed. I checked all network settings on my Mac and the remote Mac. Everything was fine. After 2h of searching and testing it turned out that the cmux app wasn’t granted the system permission to access local network 🤦‍♂️#macOS

Thorsten Stark reposted

Apple updated its Human Interface Guidelines for Sheets on March 24, 2026 to add guidance for button placement in the toolbar. "In iOS & iPadOS, the Cancel button belongs on the leading edge of the top toolbar." Time to update my apps 🙂 Documentation: developer.apple.com/design/human...

Thorsten Stark reposted

A new Zen patch arrived and here are the key highlights: ✓ QoL feature improvements ✓ Performance improvements ✓ Security improvements + bug fixes You can now also use 'Alt' + click on a tab to open a split view for an improved workflow!