Khoa Pham
Khoa Pham

Ohayo

Swift Discovery

Discover all the tech

Featured

How to make NSCollectionView with diffable data source and SwiftUI

Issue #980

NSCollectionView, available since macOS 10.5+, is a good choice to present a list of content. Let’s make a SwiftUI wrapper for NSCollectionView with diffable data source and compositional layout

Use NSViewControllerRepresentable …

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 …

How to get Supabase user token from server API

Issue #947

Sometimes Row Level Security is not enough and we want to do all logic server side, then we need a way for the server to get hold onto current user token.

Send JWT token in Authorization header

From client, we can get session from supabase …

How to mirror auth.users on Supabase

Issue #946

For security purposes, the auth schema is not exposed on the auto-generated API. We can make a profiles table in public namespace and mirror data from auth.users when user signs up.

I need id, username and raw_user_metadata so I will …

How to force localized language with SwiftGen

Issue #945

The default SwiftGen generate generated strings L10n file like this

extension L10n {
  private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String {
    let format = BundleToken.bundle. …

How to make tag flow layout using Layout protocol in SwiftUI

Issue #944

SwiftUI in iOS 16 supports Layout protocol to arrange subviews

We need to implement 2 methods

How to use hover annotation in Swift Charts

Issue #943

In this tutorial, we’ll learn how to use Swift Charts to visualize ranking data.

Screenshot 2023-08-18 at 11 48 28

We use default AxisMarks and AxisMarks to let Swift Charts interpolate x and y grid lines. For y axis, I want to have finer grain control over the …

How to use Supabase auth with React Context

Issue #942

Expose supabase with createClient

useSupabase.ts

import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.SUPABASE_URL
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY

export const supabase = …

How to create React app with Parcel

Issue #941

In this tutorial we will be creating a React app with Parcel 2 with Typescript and Tailwind

Install the following dependencies. Parcel supports TypeScript out of the box without any additional configuration.

npm install --save-dev parcel …

How to make Chrome extension with Nextjs 13

Issue #940

We can develop Nextjs 13 apps and export it to a Chrome extension.

Start by init the project

npx create-next-app@latest

Here is the project structure with app router and not using src directory. I put an extension to the root of the …

How to scale image fill without affect layout in SwiftUI

Issue #939

Instead of letting the Image decide the size, we can put it as background or overlay. I use clipped and contentShape to avoid the fill image obscuring touch event

Color.clear
    .frame(height: 100)
    .overlay {
        AsyncImage(url: …

How to move Core Data database to AppGroup folder

Issue #938

To let app and extension to talk to the same database, we need to use AppGroup. Here is how to use replacePersistentStore

Replaces one persistent store with another

actor DatabaseMigrator {
    @AppStorage( …

How to read write files to iCloud Drive

Issue #937

First, you need to enable iCloud Documents capability. Go to target settings -> Signing & Capabilities -> iCloud ` Screenshot 2023-07-28 at 16 09 14

Then inside your Info.plist, add this with your iCloud identifier and app name …

How to make reusable Button component in React

Issue #936

From https://github.com/antonioerdeljac/next13-spotify

import { forwardRef } from "react";
import { twMerge } from "tailwind-merge";

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement …

How to make fullstack web app

Issue #935

I prefer UI Component that works with Nextjs and Tailwind CSS

UI Libraries

How to use keychain in Swift

Issue #934

There are a few keychain wrappers around but for simple needs, you can write it yourself

Here is a basic implementation. I use actor to go with async/await, and a struct KeychainError to contain status code in case we want to deal with …

How to handle route case sensitivity in Nextjs

Issue #933

By default, Nextjs route is case sensitive, so localhost:3000/About and localhost:3000/about are different routes.

To make uppercase routes become lowercase routes, we can add a middleware.tsx file to the src so it is same level as pages …

How to make share and action extension in iOS

Issue #932

Add Share extension and Action extension respectively in Xcode. We can use the same code to both extension

Screenshot 2023-07-12 at 21 11 41

SwiftUI

I usually make a ShareView in SwiftUI with ShareViewModel to control the logic

struct ShareView: View {
    @ …

AppStore screenshots size checklist

Issue #931

AppStore screenshots

Screenshot specifications

iPhone 6.7"

Portrait 1290 x 2796

iPhone 6.5"

Portrait 1242 x 2688

In-App Purchase screenshots

In-app purchase information

iOS 640 x 920 tvO 1920 x1080 pixels macOS 1280 x 800 pixels

How to use AppIntents in iOS 16

Issue #930

AppIntents

Declare AppShortcutsProvider, note that appShortcuts uses @AppShortcutsBuilder syntax

import AppIntents

struct OurShortcutsProvider: AppShortcutsProvider {
    static var shortcutTileColor: ShortcutTileColor = .lightBlue …

How to press and hold button in SwiftUI

Issue #929

We can use ButtonStyleConfiguration to detect isPressed state

struct RecordButton: View {
    var body: some View {
        Button {
        
        } label: {
            Image(systemSymbol: .micFill)
        }
        .buttonStyle( …

How to copy text to the clipboard in Swift

Issue #928

For iOS, use string

Setting this property replaces all current items in the pasteboard with the new item. If the first item has no value of the indicated type, nil is returned.

let pasteboard = UIPasteboard.general
pasteboard.string = …

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