• Working with percentages in SwiftUI layout

    SwiftUI’s layout primitives generally don’t provide relative sizing options, e.g. “make this view 50 % of the width of its container”. Let’s build our own! Use case: chat bubbles Consider this chat conversation view as an example of what I want to build. The chat bubbles always remain 80 % as wide as their container as the…

    Read More

  • How the relative size modifier interacts with stack views

    And what it can teach us about SwiftUI’s stack layout algorithm I have one more thing to say on the relative sizing view modifier from my previous post, Working with percentages in SwiftUI layout. I’m assuming you’ve read that article. The following is good to know if you want to use the modifier in your…

    Read More

  • How the Swift compiler knows that DispatchQueue.main implies @MainActor

    You may have noticed that the Swift compiler automatically treats the closure of a DispatchQueue.main.async call as @MainActor. In other words, we can call a main-actor-isolated function in the closure: import Dispatch @MainActor func mainActorFunc() { } DispatchQueue.main.async { // The compiler lets us call this because // it knows we’re on the main actor.…

    Read More

  • Building with nightly Swift toolchains on macOS

    The Swift website provides nightly builds of the Swift compiler (called toolchains) for download. Building with a nightly compiler can be useful if you want to check if a bug has already been fixed on main, or if you want to experiment with upcoming language features such as Embedded Swift, as I’ve been doing lately.…

    Read More

  • Tracking renamed files in Git

    Git famously doesn’t track file renames. That is, Git doesn’t store the information “file A has been renamed to B in commit X”. Instead, Git stores snapshots of the repository at each commit. It then uses a (customizable) heuristic during diffing to guess at likely renames: “File B in commit X is new, and file…

    Read More

  • Use ‘git mv’ to record filename case changes in Git

    After my previous post Tracking renamed files in Git, here’s another entry in my ongoing series “I thought git mv was useless but I was wrong”. This one’s especially relevant to users on macOS and Windows, where the file system is case-insensitive by default. More precisely, APFS on macOS is case-insensitive but case-preserving by default.…

    Read More

  • Advanced Swift, fifth edition

    We released the fifth edition of our book Advanced Swift a few days ago. You can buy the ebook on the objc.io site. The hardcover print edition is printed and sold by Amazon (amazon.com, amazon.co.uk, amazon.de). Highlights of the new edition: Fully updated for Swift 5.6 A new Concurrency chapter covering async/await, structured concurrency, and…

    Read More

  • A heterogeneous dictionary with strong types in Swift

    The environment in SwiftUI is sort of like a global dictionary but with stronger types: each key (represented by a key path) can have its own specific value type. For example, the .isEnabled key stores a boolean value, whereas the .font key stores an Optional<Font>. I wrote a custom dictionary type that can do the…

    Read More

  • AttributedString’s Codable format and what it has to do with Unicode

    Here’s a simple AttributedString with some formatting: import Foundation let str = try! AttributedString( markdown: “Café **Sol**”, options: .init(interpretedSyntax: .inlineOnly) ) AttributedString is Codable. If your task was to design the encoding format for an attributed string, what would you come up with? Something like this seems reasonable (in JSON with comments): { “text”: “Café…

    Read More

  • How @MainActor works

    @MainActor is a Swift annotation to coerce a function to always run on the main thread and to enable the compiler to verify this. How does this work? In this article, I’m going to reimplement @MainActor in a slightly simplified form for illustration purposes, mainly to show how little “magic” there is to it. The…

    Read More