Swift Discovery

Hi there, I’m Khoa aka onmyway133 👋

  • 🧑‍💻 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

How to use React Custom Hooks as the View Model pattern

Issue #975 When building a React application, separating the logic and state management from the UI can make your code easier to manage, test, and reuse. This is where the view model pattern comes in handy. By using a custom hook as a view model, you can keep your components focused on displaying the UI while the hook handles all the complex logic and state. Let’s break down how to do this with a simple example....

July 16, 2024 · 5 min · 967 words · Khoa

How to use memory in lowdb

Issue #974 In lowdb 7, we can use MemorySync https://github.com/typicode/lowdb/blob/main/src/examples/in-memory.ts import { LowSync, MemorySync, SyncAdapter } from '../index.js' import { JSONFileSync } from '../node.js' declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace NodeJS { interface ProcessEnv { NODE_ENV: 'test' | 'dev' | 'prod' } } } type Data = Record<string, unknown> const defaultData: Data = {} const adapter: SyncAdapter<Data> = process.env.NODE_ENV === 'test' ? new MemorySync<Data>() : new JSONFileSync<Data>('db.json') const db = new LowSync<Data>(adapter, defaultData) db....

July 11, 2024 · 1 min · 75 words · Khoa

How to detect Barcode and QR code

Issue #973 Before iOS 11, we used to use CIDetector and CIDetectorTypeQRCode to detect QR code CIDetector An image processor that identifies notable features, such as faces and barcodes, in a still image or video. CIDetectorTypeQRCode A detector that searches for Quick Response codes (a type of 2D barcode) in a still image or video, returning CIQRCodeFeature objects that provide information about detected barcodes. func readQrOnly(image: CGImage) async -> String? { let ciImage = CIImage(cgImage: image) let detector = CIDetector( ofType: CIDetectorTypeQRCode, context: nil, options: [ CIDetectorAccuracy: CIDetectorAccuracyHigh ] ) guard let detector = detector else { return nil } let features = detector ....

June 6, 2024 · 2 min · 271 words · Khoa

How to make swifty UserDefaults

Issue #972 We want to have a swifty UserDefaults API that works with subscript and in a type safe manner. extension Defaults.Keys { static let string = Defaults.Key("string", default: "0") } XCTAssertEqual(defaults[.string], "0") defaults[.string] = "1" XCTAssertEqual(defaults[.string], "1") UserDefaults plist compatibility Define Compatible protocol that allows value to be plist compatible The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects....

May 28, 2024 · 3 min · 504 words · Khoa

How to use act vs waitFor using React Testing Library

Issue #971 When testing React components, dealing with tasks that happen at different times is super important to make sure your tests give reliable results. React Testing Library gives you two important tools for dealing with these situations: act and waitFor. Even though they both help with handling actions that don’t happen right away, they’re used in different situations. act: Ensuring Synchronous Updates The act function wraps parts of your code that cause updates linked to changes in state, effects, or other delayed actions....

March 13, 2024 · 4 min · 672 words · Khoa

How to use OSLog and OSLogStore in Swift

Issue #970 We can use Logger to log and OSLogStore to retrieve logs import OSLog import ReuseAcross final class LogService { static let shared = LogService() let logger = Logger( subsystem: "com.example.myapp", category: "Log" ) func export() -> [String] { do { let store = try OSLogStore(scope: .currentProcessIdentifier) let position = store.position(timeIntervalSinceLatestBoot: 1) let logs = try store .getEntries(at: position) .compactMap { $0 as? OSLogEntryLog } .filter { $0.subsystem == Bundle....

February 8, 2024 · 1 min · 104 words · Khoa

How to include custom error payload in hapi Boom

Issue #969 Hapi.js, commonly referred to as Hapi, is an open-source, back-end web application framework for building and deploying web applications and APIs in Node.js In Hapi.js, you can use the Boom module to create and return error responses in a standardized way. Boom provides a set of functions to generate HTTP error objects with consistent properties, making it easier to handle errors and communicate them to clients Read Error transformation...

January 31, 2024 · 1 min · 114 words · Khoa

How to read image paste from clipboard in React

Issue #968 Are you looking to grab images directly from your clipboard with a button click on your web page? The Async Clipboard API makes this quite easy and efficient. Let’s break it down into simpler steps: Requesting Permission The first time you try to read something from the clipboard using this method, your browser will ask for permission. This is a security feature to ensure that websites don’t access your clipboard without your consent....

January 30, 2024 · 2 min · 261 words · Khoa

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 create personalized ignore rules for your local Git setup without changing the global project settings. gitignore Before we get into .user_gitignore, let’s quickly go over what a regular .gitignore file does....

January 30, 2024 · 2 min · 280 words · Khoa

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 other type, gets created in memory when the code within a function’s scope is executed. This poses a challenge for React’s rendering logic, which determines the need for re-rendering based on changes in input props and context....

January 26, 2024 · 2 min · 398 words · Khoa

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 object-oriented programming languages like Java or C#. Extending classes is also a feature of ES6, which allows you to create a new class from an existing class. This is done through the extends keyword....

January 25, 2024 · 4 min · 689 words · Khoa

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 export * syntax is used to re-export all exportable members from the imported module. It’s a way to aggregate exports from several modules into a single module. For example, let’s say we have a couple of modules, each exporting some components:...

January 25, 2024 · 2 min · 397 words · Khoa

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 handled appropriately to ensure they don’t inadvertently affect the structure or behavior of our code. Traditionally, we negate their special meaning by escaping them with backslashes. However, Swift provides an even simpler method — raw strings....

January 12, 2024 · 4 min · 812 words · Khoa

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: “absolute” style. <div className="relative"> <Image src="" alt="" fill objectFit="cover" /> </div>

January 7, 2024 · 1 min · 48 words · Khoa

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 } }

January 7, 2024 · 1 min · 29 words · Khoa

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 use math, I’ve wished this was possible. Now, with advances in machine learning and vision recognition in iOS, this is doable. In this guide, I’ll provide some of the technical details for working with Vision in iOS, as well as my personal experiences using this technology....

December 31, 2023 · 12 min · 2460 words · Khoa

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", "link": "https://indiegoodies.com/shipmunk" }, "pastepal": { "name": "PastePal", "link": "https://indiegoodies.com/pastepal" }, "codelime": { "name": "Codelime", "link": "https://indiegoodies.com/codelime" } } Decoding JSON with dynamic keys in Swift can be tricky because the keys in your data can change, and Swift likes to know exactly what it’s working with ahead of time....

December 21, 2023 · 2 min · 378 words · Khoa

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. The polyfill is a way to bring modern JavaScript features and APIs to older browsers that don’t support them natively. Before ES6 (ECMAScript 2015), JavaScript lacked many features that are now considered standard....

December 7, 2023 · 2 min · 251 words · Khoa

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 = {}; """ ) let consoleLog: @convention(block) (Any) -> Void = { print($0) } objectForKeyedSubscript("console") .setObject(consoleLog, forKeyedSubscript: "log" as NSString) } } Then we can just call let context = JSContext()! context.injectConsoleLog() context.evaluateScript(jsContent)

December 7, 2023 · 1 min · 60 words · Khoa

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 { let parent: AttributedTextView init( parent: AttributedTextView ) { self.parent = parent super.init() } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeNSView(context: Context) -> NSScrollView { let view = NSTextView.scrollableTextView() if let textView = view.documentView as? NSTextView { textView.font = NSFont.preferredFont(forTextStyle: ....

December 7, 2023 · 2 min · 257 words · Khoa