The Documentation
I document my frameworks, failures, and daily builds so you can use them.
2026
Dots N Bars (post-1.2.1 build) — I changed the plank to start at 2 segments and grow to 3 then 4 as score crosses fixed thresholds, instead of always being 4. I also added the project’s first test target — 31 unit tests covering the new scoring and matching rules, written as plain functions so they run without SpriteKit or a simulator.
2026
Canopy build 9 (unreleased, pending merge) — Fixed a data-loss bug where an involuntarily interrupted recording (permission revoked mid-flight) could be silently wiped by the next tap of “Record,” and a trim-tool bug that let both handles land on the same point and save, collapsing the flight to a single point with no recovery path in the UI.
2026
Dots N Bars (post-1.2.1 build) — Added a drop type that matches no color currently on the plank — touching it now ends the run, and letting it fall through is the correct play. While building this I found the existing plank-drag clamp was mathematically too narrow to ever dodge a drop (its radius was smaller than the plank’s own width), so I widened it.
2026
Pixel Edit Lite v1.4.0 (build 12) — Sharing a sprite saved it as .com.apple.Foundation.NSItemProvider.P48iCO.png — the generic fallback name iOS assigns when a shared item has no filename of its own. I fixed it by switching from DataRepresentation to FileRepresentation, writing a real temp file first, so shares now save as PixelEdit-Sprite-8x8-2026-09-05-091600.png.
2026
Pixel Edit Lite v1.4.0 (build 12) — New Sprite Sheet used to wipe the sprite sheet outright behind a confirm dialog. I changed it to silently save the outgoing sheet to disk via a security-scoped bookmark before clearing, so the action needs no confirmation now and nothing is lost — the same check runs before Import and before reopening a past file too.
2026
Dots N Bars 1.2.1 (build 11) — A plank’s 4 segments are always distinct colors, so a drop landing exactly on a segment boundary always touches one matching and one non-matching segment in the same physics step, and SpriteKit doesn’t guarantee delivery order between them. If the matching contact happened to be processed first, the mismatch was silently dropped and the drop scored instead of ending the run. Fixed by deferring the outcome to didSimulatePhysics(), which runs once per step after every contact has been delivered, so a same-step mismatch always wins regardless of order.
2026
Pixel Edit Lite v1.3.2 (build 11) — Added VoiceOver labels across the toolbar and menu chrome. The one non-trivial part was the Shape tool’s long-press (toggles filled/outlined) — VoiceOver’s standard double-tap activation can’t trigger a long-press, so I exposed it separately as a named accessibility action via .accessibilityAction(named:) rather than leaving that functionality unreachable for VoiceOver users.
2026
Dots N Bars 1.2.1 (build 10) — Found on a physical device: the red failure flash could freeze mid-fade and linger on the restart screen, tinting it red. Root cause was one node that was never tagged for the game-over cleanup sweep that removes transient effects — the cleanup logic itself was correct, this one node was just missed.
2026
Canopy (build 9) — Ran a full release-hardening pass ahead of App Store submission: fixed import-correctness edge cases, tightened privacy handling, and closed out the remaining App Store readiness items.
2026
Dots N Bars 1.2.1 (build 9) — Catch matching compared rendered fillColor between the drop and plank segment, which was only coincidentally reliable. Gave both an explicit matchColor set once at init, and backed score with a private store so a score reset can never accidentally trigger the best-score/celebration logic — true by construction instead of by 0 never exceeding the best score.
2026
Dots N Bars 1.2.1 (build 8) — The color palette was defined in two separate lists that could silently drift apart — adding a color to one without the other would show a “?” glyph instead of a real symbol. Centralized it into one source of truth, and replaced the start-menu title’s hardcoded character-offset coloring with self-describing (text, color) pairs so a future text edit can’t silently miscolor the wrong letters.
2026
Dots N Bars 1.2.1 (build 8) — applicationWillResignActive was an empty stub, so a phone call or notification pull left the game running unpaused for the full transition window. Added a NotificationCenter observer that reuses the existing pause-button logic instead of a second state machine.
2026
Space Jam v1.1.2 (unreleased) — Three properties (starfield, backgroundMusic, an explosion sprite) were implicitly-unwrapped optionals fed by SpriteKit’s failable initializers, so a missing or renamed asset file would force-unwrap nil and crash. I replaced them with local guard let/if let bindings that log and skip the effect instead of crashing, then added the project’s first test target — 4 XCTests locking in the enemy spawner’s dodge-lane and speed-sync guarantees.
2026
Dots N Bars 1.2.1 (build 8) — Neither the drop nor the plank segments set collisionBitMask, so SpriteKit was resolving a real physical collision between them on every catch in addition to the contact-test callback — when a drop’s circle overlapped two flush segments at once, the catch callback fired twice, and the second call force-unwrapped an already-nil drop and crashed. Fixed by resolving the drop from the actual contact node and setting collisionBitMask = 0 on both, since the relationship was only ever meant to be a contact test.
2026
Space Jam v1.1.2 (unreleased) — High scores were only written to UserDefaults at game-over, so a crash or force-quit mid-run could lose a new best score that never touched disk. I moved the write into score’s didSet, right where bestScore updates, so it persists the instant the record is broken.
2026
Pixel Edit Lite v1.3.1 (build 10) — Shift previously clipped: pixels pushed off one edge of a sprite were just deleted and replaced with the erase color. Checked how real PICO-8 handles this first, confirmed it wraps instead of clipping, then replaced the bounds-check-and-erase branch with modular index arithmetic so shifted pixels now reappear on the opposite edge with zero loss.
2026
Dots N Bars 1.2.0 (build 7) — Archived build 6 under the version string 1.2, but the App Store Connect version shell had been typed as 1.1.1 then corrected to 1.2.0 — a string mismatch that blocks attaching the build. Build numbers turned out to be permanent per bundle ID too, so build 6 couldn’t be reused once corrected; had to burn it and re-archive as build 7.
2026
Canopy (build 8) — Fixed an IGC midnight-UTC rollover bug where baseMidnight + timeOfDay timestamps ran backwards for any flight crossing midnight, corrupting sort order and duration. Also fixed a flight save that could fail silently with no error shown to the pilot.
2026
Space Jam v1.1.1 (Build 5-6) — A difficulty bump only applied its new fall speed to rows spawned after it — anything already on screen kept its old, slower velocity, so a freshly-spawned fast row could catch up to an older slow one and wall off a lane right at the transition. I extracted baseFallSpeed into a single named constant and added syncActiveEnemiesToCurrentSpeed(), called the instant the multiplier changes, so nothing on screen is ever moving at a stale speed.
2026
Space Jam v1.1.1 (Build 5-6) — SKPhysicsBody(texture:size:) bakes its collision shape at creation time and never re-reads .setScale() afterward, so enemy hitboxes stayed full-size even after I shrunk the sprites 0.8x to widen dodge gaps — collisions didn’t match what the player saw on screen. Fixed it by explicitly computing the scaled CGSize and passing it into the physics body constructor instead of relying on the node’s transform.
2026
Dots N Bars 1.2.0 — Added a live celebration — haptic, gold screen flash, particle burst, and a gold-tinted score label — that fires the instant a run’s score passes the previous best, instead of only showing it after the fact on the restart screen. First version relied on the gold flash alone, which didn’t read as distinct from a normal perfect catch on-device; added an explicit “NEW BEST!” text banner to fix that.
2026
Space Jam v1.1.0 (Build 3-4) — The spawner could roll all 3 lanes in a single row, which is an unwinnable state — there’s no lane left to dodge into. I rewrote it to pick 1-2 lanes per row from a shuffled array, guaranteeing at least one always stays open.
2026
Space Jam v1.1.0 (Build 3-4) — Pulled enemy-spawning logic out of the 250-line GameScene god object into its own EnemySpawner class and added a progressive difficulty curve (spawn interval and fall speed both ramp with score). Switched controls again, this time to split-screen tap zones, after swipe gestures proved less reliable for rapid lane changes.
2026
Dots N Bars 1.2.0 — The entire game mechanic is color matching with zero accommodation for colorblind players. Added a shared color-to-glyph mapping (star, triangle, square, diamond, dot, down-triangle, plus) wired into both the drop and plank-segment rendering, so the game is playable by shape alone.
2026
Space Jam v1.1 (pre-release) — Ripped out AdMob entirely, which meant deleting 200MB+ of vendored GoogleMobileAds/GoogleAppMeasurement/nanopb binary frameworks that had been committed directly into the repo instead of pulled via a dependency manager. Replaced tap-to-move lane switching with UISwipeGestureRecognizer-based swipe controls, and fixed the score label sitting under the status bar by anchoring it to view.safeAreaInsets.top instead of a fixed offset.
2026
Space Jam v1.1 (pre-release) — willMove(from:) never invalidated the spawn Timer, so leaving the scene left a zombie spawner retaining self and firing into a dead scene. I added the missing invalidate() call and swapped three hardcoded pixel coordinates (80, 190, 300) for frame.width percentages so lane positions stop breaking on non-iPhone-8 screen sizes.
2026
Pixel Edit Lite v1.3.0 (build 9) — Migrated flood fill, rotate, and shift off whole-buffer operations onto a bounded (origin, regionSize) window as part of moving to an always-on 128×128 sprite sheet, so editing one sprite can no longer flood-fill or rotate across the other 255 slots on the same sheet. Also replaced wiping the entire undo history on every transform with proper single-step undo, since a bounded region write can go through the same per-pixel history path as normal drawing.
2026
Dots N Bars 1.1 (build 5) — Tried setting the marketing version to 1.0 for a fresh release line, since the original 2020 listing had been delisted. App Store Connect rejected it outright — version 1.0 had already been approved once and Apple’s version-history lock on a bundle ID is permanent regardless of whether the listing was later removed — so reverted to 1.1.
2026
Pixel Edit Lite v1.2.2 (build 8) — The palette-change confirmation alert had stopped appearing. Traced it to PalettePickerView calling both the environment dismiss() action and setting its own popUp binding to false in the same tap handler — two overlapping dismissal triggers on one sheet, which was swallowing the alert that was supposed to follow. Removed the redundant dismiss() call and let the alert fire from .onDisappear once the sheet had actually finished closing.
2026
Dots N Bars 1.1 (build 5) — bestScore was updated in memory on a new high but never written to UserDefaults, so the displayed best score silently reverted to whatever was last saved on every relaunch. Also fixed a memory leak where the score popup’s animation sequence never called removeFromParent(), permanently leaving an invisible node in the scene graph on every single catch.
2026
Canopy (build 7) — Fixed the app’s accent color, which had drifted from the brand teal in Settings and icon badges.
2026
Pixel Edit Lite v1.2.1 (build 5) — A user reported Undo reverting strokes from several pixels back instead of the most recent one. Root cause was an unstructured Task { @MainActor in ... } wrapping every pixel write with no actual async work inside it — if the drag’s .onEnded fired before a queued write executed, that pixel landed in the next stroke’s undo entry instead of its own. Made the write path synchronous and verified with a three-tap sequence (red, blue, yellow) that each Undo now removes exactly one stroke in the right order.
2026
Pixel Edit Lite v1.2.0 (build 4) — Added local autosave: the app now serializes the sprite buffer to a CanvasSnapshot in Application Support when it backgrounds, and restores it on next launch. Undo/redo history is deliberately excluded from what’s saved — it was already scoped to a single session, so autosave doesn’t change that.
2026
Dots N Bars 1.1 (build 4) — Gravity increased by a fixed amount on every catch with no ceiling, so fall time kept shrinking indefinitely — past roughly catch 35–40 it dropped under the ~0.5s floor needed to see a drop, judge its color, and react, meaning every long run was ending from the game outrunning human reaction time rather than an actual mistake. Capped gravity at a fixed maximum so difficulty plateaus into a sustained challenge instead of a hidden wall.
2026
Dots N Bars 1.1 (build 4) — Fixed a plank-reachability bug I’d introduced in an earlier width change that day — clamping the plank to stay fully on-screen over-constrained its range and made the two edge segments mathematically unable to ever reach a drop spawned at certain x positions. Recentered the clamp on the drop’s actual spawn x instead, and made drop spawn position randomized rather than fixed, since a fixed spawn point made “perfect” catches trivial to memorize.
2026
Dots N Bars 1.1 (build 4) — Added a perfect-catch bonus: a catch within 15pt of a segment’s center now scores +2 instead of +1, with distinct visual feedback so the bonus is readable at a glance.
2026
Dots N Bars 1.1 (build 4) — Found that triggerGameOverFeedback()’s sound/shake/flash were being scheduled during the physics-simulation phase of a frame, one frame after update() had already paused the scene — so the feedback sat queued and paused until the player resumed, and effectively only played on resume, not on the actual failure. Fixed by splitting “detect game over” from “freeze and tear down” into two states so the scene stays unpaused for a ~0.35s feedback window first.
2026
Dots N Bars 1.1 (build 4) — Split the plank and drop into their own SKShapeNode subclasses (previously inlined directly in the scene) and added a real Start Menu/Pause overlay flow plus haptic feedback, replacing an old scene-transition-based game-over screen.
2026
Dots N Bars 1.1 (build 4) — Removed the vendored GoogleMobileAds/GoogleAppMeasurement SDK entirely, along with the arm64-simulator-exclusion workaround that existed only because of it. While auditing the code I found two real bugs: nothing stopped a new drop from spawning before the previous one was resolved (could silently orphan a drop), and the scene rendered at a fixed 375x667 with .aspectFit, letterboxing on every other screen size — switched to .resizeFill with layout-time safe-area insets so the score label also clears the notch.
2026
Canopy (build 7) — Reworked Replay around a real cursor/clock instead of a hacked animation loop, unified GPX/IGC/TCX import into one shared pipeline, and fixed a bug where reimporting a file created a duplicate glider instead of reusing the existing one by name.
2026
Canopy (build 5) — Fixed a set of unit-conversion bugs where altitude was being converted twice across several charts, then rewrote the flight-metrics engine with rolling-window algorithms and added a dedicated test suite to stop it from regressing again.
2026
Canopy (build 3–4) — Added a universal aviation equipment schema, hold-to-stop recording with background-tracking permissions, and a flight-trimming tool. Fixed a crash in IGCParser caused by unsafe string extraction on malformed records.
2026
Pixel Edit Lite v1.1.0 (build 2) — Revived the project after roughly three and a half years dormant and modernized the whole data model off ObservableObject/@Published onto Swift’s @Observable macro, plus moved the canvas from a custom rendering approach to SwiftUI’s Canvas API. Touched every core file in the app (CanvasDataModel, CanvasView, ColorPaletteView, ToolBoxView) in one pass to get it building clean on Swift 6.
2026
Canopy (build 3) — Rebranded the app from Zephyr to Canopy and completed the V1 launch checklist, then fixed flight-stats and site-picker bugs found right after.
2026
Dots N Bars 1.1 (build 2) — Fixed a GoogleMobileAds SDK linking error on simulator builds by excluding the arm64 simulator architecture. Also modernized the layout constraints, added haptic feedback, and removed several force-unwraps that could crash.
2026
Zephyr (pre-release) — Added CSV export, social-sharing flight snapshots, and climb-rate-colored flight paths with takeoff/landing markers on the map. Fixed a MapKit DRM bug that produced a yellow screen and an auto-record bug.
2026
Zephyr (pre-release) — Added IGC file import, a first onboarding flow, and a pitched 3D map camera. Also fixed a Site model initializer bug where a parameter shadowed itself and a main-thread block during TCX/IGC imports.
2026
Zephyr (pre-release) — Built FlightRecorderService to record a flight live via GPS instead of only importing files, and made the SwiftData models CloudKit-compliant by giving every non-optional property a default value.
2026
Zephyr (pre-release) — Rebuilt the flight list into a Strava-style dashboard with month grouping and search, and moved all file import/processing onto a background ModelActor so large files no longer block the UI thread.
2025
Zephyr (pre-release) — Added the app’s first icon. Development paused here for about ten months.
2025
Zephyr (pre-release) — Added a user-configurable unit system (metric/imperial) and cleaned up duplicated duration-parsing logic between the manual entry and edit forms.
2025
Zephyr (pre-release) — Moved file parsing off the main thread and added a progress indicator so importing a file no longer freezes the UI while it processes.
2025
Zephyr (pre-release) — Added 3D terrain to the map view with the flight path colored by speed, then built a full flight Replay feature on top of the same track data.
2025
Zephyr (pre-release) — Started the project: SwiftData models for flights, manual flight entry, and TCX file import with a map view. Added flight stats, a settings screen, and the ability to edit or delete a saved flight.
2023
Last run on Xcode 14.2, iOS 16.2, and Swift 5.7.2 Picker View for Time Durations In my Timer app, I needed a Picker View for taking the timer interval …
Read full →2023
Last Run on XCODE 14.2 / iOS 16.2 / Swift 5.7.2 Change the Back Button’s Icon If you have used the default Settings App that comes with iOS, you …
Read full →2023
Last Run on Python 3.11.1 Intro I have been working on a SwiftUI app to develop a Pixel Editor inspired by the simplicty of the pico8 fantasy game …
Read full →2023
Last Run on XCODE 14.2 / iOS 16.2 / Swift 5.7.2 Making a Dynamic Button If you have noticed, the play button on most media players changes to pause …
Read full →2023
Is 2023 the year I blog more frequently? I have been blogging on/off for the past decade. This is another attempt at rekindling the fire. The …
Read full →2023
Space Jam v1.0 (2020 baseline) — Brought the original 2020 build under git for the first time. I had no version control history for this project before this point — everything prior lived only as local file copies.
2023
Last Run on XCODE 14.2 / iOS 16.2 / Swift 5.7.2 Progress View Ring I was building a Timer app and needed a visual indicator to display the the amount …
Read full →2020
Last Run on XCODE 11.6 / Swift 5.2 Last Run on XCODE 12.0 beta 4 / Swift 5.3 Definition Calendar - A definition of the relationships between calendar …
Read full →2020
Last Run on XCODE 11.6 / Swift 5.2 Definition CaseIterable is a protocol in Swift, that typically lets an enumeration to provide all of its cases as a …
Read full →2020
Last Run on XCODE 11.6 / Swift 5.2 Definitions ‘TextField’ is a View provided in SwiftUI for handling user entered input into an app. As …
Read full →2020
Last Run on XCODE 11.6 / Swift 5.2 In SwiftUI View(s) are the building blocks of the UI. All changes to the Views are done by calling special …
Read full →2020
Last Run on XCODE 11.4 / Swift 5.2 If you are writing a command line tool and need user input, the readLine() function can be used for it. It returns …
Read full →2020
Last Run on XCODE 11.4 / Swift 5.2 A simple way to check if a string contains a certain text is to use the method contains available to Strings. In …
Read full →2020
Last Run on XCODE 11.4 / Swift 5.2 A simple way to check if a string starts or ends with a certain pattern is to use the method hasSuffix and …
Read full →2020
Last Run on XCODE 11.4 / Swift 5.2 The swift string class does not provide the ability to get a character at a specific index because of its native …
Read full →2020
Last Run on XCODE 11.4 / Swift 5.2 Spritekit has a method enumerateChildNodes that searches the children of the receiving node to perform processing …
Read full →2019
We often take pictures of menus, receipts, and message boards etc. They are often not aligned properly. In this post, I will show you how to select …
Read full →2019
In this blog post, I will show you how we can enhance our images using colored filters and add border backgrounds. Original Original w/ color filter …
Read full →2019
In a series of upcoming blog posts, I will be using OpenCV to manipulate images. In this post, I will be adding text to an image (below), I took of a …
Read full →2019
Continuing the theme of exploring Go Lang, today I will be writing a simple version of the Unix utility wc that displays the number of lines, words, …
Read full →2019
I am currently dabbling in [GoLang] go-lang and trying to get familiar with it’s syntax and style of programming. I also want to get familiar …
Read full →2019
“ls” is unix utility that lists the files and directories in the current path or a user passed path. In this post we will explore how to …
Read full →2012
Sum of the Squares of the first 5 numbers In this post I will try to use the map() and reduce() functions to compute the sum of the squares of the …
Read full →2012
Memoization is a computer science concept to optimize programs by avoiding computations that have already been done and to reuse it. This is achieved …
Read full →2011
Traceroute Traceroute is a network diagnostic utility used for displaying the path taken by a packet to it’s destination. It uses the ICMP …
Read full →2011
What is DHCP ? DHCP is a protocol used to provide an IP address to a device. It is also used to configure additional networking related parameters on …
Read full →2011
A year ago, I fired up wire shark on my home network to check out the packet flow of the DHCP process. I closed all my browser windows and other …
Read full →