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 create user gitignore

Issue #967

Git is a helpful tool for managing code and projects, but sometimes you want to ignore certain files or folders only on your computer without affecting everyone else. That’s where the .user_gitignore file comes in. It allows you to …

How to use useCallback in React

Issue #966

The use of useCallback and useMemo in React hooks is an adaptation to address certain limitations inherent in the functional programming style adopted by React. In JavaScript, every entity, whether it’s a function, variable, or any …

How to extend class in Javascript

Issue #965

In JavaScript, classes are a template for creating objects. They encapsulate data with code to work on that data. ES6 introduced a class syntax to the JavaScript language to create classes in a way that’s similar to other …

How to use export all and export default in Javascript

Issue #964

In JavaScript, particularly in modules used in frameworks like React, export statements are used to expose code—such as functions, classes, or constants—from one module so that they can be imported and reused in other modules.

export *

The …

How to escape characters in json and regex with Swift string

Issue #963

In the world of Swift programming, we often come across situations where we need to work with string literals that contain special characters. These characters can include new lines, tabs, backslashes, and quotes — all of which need to be …

How to use nextjs Image

Issue #962

Fill parent div

A boolean that causes the image to fill the parent element, which is useful when the width and height are unknown.

The parent element must assign position: “relative”, position: “fixed”, or position: …

How to check NSTextField is first responder

Issue #961

NSTextField uses NSFieldEditor under the hood, you can check currentEditor if it is the firstResponder

extension NSTextField {
    var isFirstResponder: Bool {
        currentEditor() == window?.firstResponder
    }
}

Building an iOS camera calculator with Core ML’s Vision and Tesseract OCR

Issue #960

Also written on Fritz


Math might be scary, but it’s an essential part of everyday life. Wouldn’t it be cool if we could build an app, point our phone’s camera at an expression, and let the app compute the result? Whenever I’ve needed to …

How to decode dynamic JSON key with JSONDecoder

Issue #959

Decoding JSON in Swift is most of the time very straightforward with help of Codable protocol and JSONDecoder.

Sometimes the json contains dynamic key, like

{
    "shipmunk": {
        "name": "Shipmunk", …

How to bundle js for use in JavaScriptCore in Swift

Issue #958

We can use any bundler, like Parcel, Webpack or Vite. Here I use Webpack 5

Install Webpack and Babel

npm install @babel/polyfill webpack webpack-cli --save-dev

@babel/polyfill is a package provided by Babel, a popular JavaScript compiler. …

How to handle log in JSContext with JavascriptCore

Issue #957

Define console object and set log function to point to our Swift function

import JavaScriptCore

extension JSContext {
    func injectConsoleLog() {
        
        evaluateScript(
        """
            var console = {}; …

How to make attributed TextView for macOS and iOS with SwiftUI

Issue #956

macOS

import Foundation
import SwiftUI
import AppKit

struct AttributedTextView: NSViewRepresentable {
    @Binding var attributedText: NSAttributedString
    var isEditable: Bool = true
    
    final class Coordinator: NSObject { …

Apple Developer Learning resources

Issue #955

Besides WWDC videos & documentation, Apple also has interactive tutorials and books. Below are some of my favorites learning resources

Tutorials

How to show anchor bottom view in SwiftUI

Issue #954

From iOS 15, there’s a handy safeAreaInset that allows us to place additional content extending the safe area.

Shows the specified content beside the modified view.

safeAreaInset allows us to customize which edge and alignment we …

How to debounce text input in React

Issue #953

Use debounce from lodash and useCallback to memoize debounce function

import React, { useCallback } from "react"
import debounce from "lodash/debounce"

const SearchField = (props: Props) => {
    const callback = …

How to remove duplicates in Javascript array while keeping latest occurrence?

Issue #952

Use ES6 Map

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

type Deal = {
    name: string,
    link: …

How to drag multiple files in SwiftUI on Mac

Issue #951

Create a custom NSView that handles mouseDragged to beginDraggingSession

struct DraggingSourceViewWrapper: NSViewRepresentable {
    let fileUrls: [URL]
    let onEnd: () -> Void
    
    func makeNSView(context: Context) -> …

How to dynamically build tailwind class names

Issue #950

Inspired by shadcn

Combine

  • tailwind-merge: Utility function to efficiently merge Tailwind CSS classes in JS without style conflicts.
  • clsx: constructing className strings conditionally.
import { clsx, type ClassValue } from "clsx" …

How to store Codable in AppStorage

Issue #949

AppStorage and SceneStorage accepts RawRepresentable where value is Int or String.

Creates a property that can read and write to a string user default, transforming that to RawRepresentable data type.

init(wrappedValue:_:store:)

init( …

How to update widget for iOS 17

Issue #948

iOS 17 has a new Stand by mode so SwiftUI introduces containerBackground for the system to decide when to draw background. It also automatically applies margin to widget so we may need to disable that

To update existing widgets, 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