Khoa Pham
Khoa Pham

Ohayo

Swift Discovery

Discover all the tech

Featured

My year in review 2020

Issue #715

I remember this time last year in December 2019, I spent almost every single bit of my free time on Puma because I want a Swift friendly version of fastlane that suits my need and leverages Swift 5 features.

Here’s my review of my …

A better way to update UICollectionView data in Swift with diff framework

Issue #1010

Medium post https://medium.com/@onmyway133/a-better-way-to-update-uicollectionview-data-in-swift-with-diff-framework-924db158db86


A Better Way to Update UICollectionView Data in Swift with Diff Framework

Familiar Friends

It’s hard …

How to wrap UserDefaults with Observable in SwiftUI

Issue #1009

SwiftUI’s Observation framework makes reactive UI updates effortless—when a property changes, views that depend on it automatically refresh. But what happens when your data lives in UserDefaults? You might want subscription status, …

How to connect MCP server in Claude Code

Issue #1008

Model Context Protocol (MCP) allows Claude Code to connect to external tools, databases, and services. See the official MCP documentation for more details.

Scopes and Configuration Storage

MCP servers have three scope levels that …

How to use Swift Testing

Issue #1007

How to Use Swift Testing

Testing in Swift has always required inheriting from XCTestCase and prefixing every method with test. Sound familiar? With Swift 6, Apple introduced Swift Testing — a framework that feels native to modern Swift …

How to make scale to fill NSImageView with remote Kingfisher image

Issue #1006

When building macOS apps, you often need images that fill their container while keeping their aspect ratio - like cover photos or thumbnails. NSImageView doesn’t do this well out of the box. Here’s how to build a custom …

How to bulk delete GitLab artifacts using GraphQL API

Issue #1005

GitLab CI/CD pipelines create artifacts that take up a lot of storage space. While GitLab has a UI to delete them, doing this for thousands of artifacts one page at a time is slow and boring.

In this article, we’ll build a script …

How to delete GitLab artifact

Issue #1004

We set expire_in: 1h in our CI test jobs, but old artifacts from days ago were still there. Something wasn’t working right.

After some research, we found this is a known bug in older GitLab versions. If you’re on GitLab 16.7 …

How to handle shell script with GitHub action

Issue #1003

When you build iOS applications on a self-hosted Mac runner, your CI/CD pipeline is likely to encounter a frustrating issue:

Could not find 'bundler' (2.6.9) required by your Gemfile.lock

Your machine has bundler installed. You …

How to install GitHub action runner on EC2 Mac

Issue #1002

I recently set up self-hosted runners on EC2 Mac instances for iOS builds. Here are my notes on what actually works—plus all the gotchas I hit along the way.

For complete official instructions, see GitHub’s guide on adding …

How to use Claude Code

Issue #1000

I’ve been using Claude Code daily for months. Here are my notes

Extended Thinking: The Magic Words

Claude Code has built-in thinking modes that allocate more compute for complex problems:

  • “think” → ~4K tokens …

How to get offset for a specific timezone in JavaScript

Issue #999

We want to take a timezone like "Europe/Oslo" and figure out what its offset is compared to UTC. During winter, Oslo is +01:00 (one hour ahead), and during summer it’s +02:00 (daylight saving time).

Using formatToParts() …

How to use playground in Swift file

Issue #998

Traditionally, if we wanted to quickly test a function or a piece of logic, we would open a separate Playground file (.playground).

From Xcode 26 we can have access to the new #Playground macro in Swift 6.2. This allows us to declare a …

How to morph liquid glass view transition

Issue #997

An interesting feature in iOS 26 is the ability to create morph “Liquid Glass” effects, where views with the .glassEffect() modifier can fluidly morph into one another. This is achieved using GlassEffectContainer and the …

How to prompt users to configure widgets in iOS 18

Issue #996

When creating widgets for iOS, especially those that need user input to be useful, one common challenge is guiding the user to configure them. Before iOS 18, a user would add a widget, but then would have to know to long-press it and …

How to make zoom transition animation in iOS 18

Issue #995

With iOS 18, SwiftUI introduces matchedTransitionSource and navigationtransition as a powerful new way to create zoom animations between views. This allows you to smoothly transition from a small view to a larger, more detailed view, …

How to create mesh gradient in iOS 18

Issue #994

With iOS 18, Apple introduced a powerful new tool for creating beautiful, dynamic backgrounds: MeshGradient. Forget simple two-color gradients; mesh gradients let you blend a whole grid of colors together smoothly, creating stunning, …

How to animate number change from iOS 17

Issue #993

Before iOS 17, if you wanted to animate a number changing, SwiftUI would just fade the old number out and fade the new one in. It worked, but it wasn’t very exciting.

Here’s how that looked:

struct OldCounterView: View {
    @ …

How to observe model changes in iOS 26

Issue #992

In the past, making your screen update when data changed in UIKit meant writing extra code, either with didSet, Combine or some other callbacks. Now, it’s automatic.

With the latest iOS 26 updates, UIKit can automatically watch your …

How SwiftUI StateObject and React useState defer initial value evaluation

Issue #991

When building apps in SwiftUI or React, we often need to store values that change — like a counter, user input, or a list of items.

To do this:

  • React gives us useState.
  • SwiftUI gives us @State and @StateObject.

But here’s something cool: …

How to tap again on tab bar item to scroll top in iOS

Issue #990

In many popular apps like LinkedIn, Reddit, we can tap again on a bar bar item to scroll to top. Although this behavior is not built in by iOS, we can implement that very easily.

The idea is to keep track of previous selection so we can …

Khoa Pham

Hello, I’m Khoa

I’m a thinker and storyteller with a passion for exploring the intersection of creativity and technology

🧑‍💻 I love crafting high quality and useful apps
🔥 I love open source. My GitHub open source has 2.3k followers with packages that are integrated by 45k+ apps and over 3.4m+ downloads on CocoaPods.
✍️ I write here on my blog and on Medium, which has over 2.7k+ followers with tons of articles and 90k+ monthly views.
🖥 Follow me for sharings about Swift, SwiftUI, iOS and macOS development.
Hei