Skip to content

Instantly share code, notes, and snippets.

View rnapier's full-sized avatar

Rob Napier rnapier

View GitHub Profile
@rnapier
rnapier / MainActorRun.swift
Last active April 23, 2024 13:29
Regarding MainActor.run
// In regards to https://mastodon.social/@mattiem/112285978801305971
// MainActor class with synchronous methods
@MainActor final class M {
func methodA() {}
func methodB() {}
}
// Actor that relies on M.
actor A {
@rnapier
rnapier / SelectorNotifiction.swift
Last active April 16, 2024 22:19
Musings on Notifications and Actors
/// Some exploration into how selector-based notification interact with actors.
///
/// Or in the words of Brent Simmons (@brentsimmons@indieweb.social),
/// "Selector-based Notification Observers Are Actually Good"
/// Overall, I'm reasonably convinced, in that it avoids the headaches of `deinit` in actors.
/// However, Combine-based observation is also good at this, so I don't yet have a strong opinion
/// about old-school selectors vs Combine beyond my usual nervousness around Combine.
/// Whether "I'd like to reduce Combine" is more or less powerful than "I'd like to reduce @objc"
/// is yet to be seen.
@rnapier
rnapier / DefaultValueConcurrency.swift
Last active April 12, 2024 01:30
Somewhat surprising impact of non-Sendable default values
// With Strict Concurrency
class C {}
struct S {
func f() {
Task { // Surprisingly need `@MainActor in` here to make this correct
await g() // Warning: Passing argument of non-sendable type 'C' into main actor-isolated context may introduce data races
}
}
@rnapier
rnapier / json.swift
Last active January 31, 2024 12:49
Generic JSON Decodable
import Foundation
@dynamicMemberLookup
enum JSON: Codable, CustomStringConvertible {
var description: String {
switch self {
case .string(let string): return "\"\(string)\""
case .number(let double):
if let int = Int(exactly: double) {
return "\(int)"
@rnapier
rnapier / TestVO.swift
Created July 31, 2023 20:04
Demonstration of VoiceOver bug
// Demonstration of FB12811151
// On some devices (so far we haven't found any newer than an 2020 SE2), VoiceOver will allow you to select
// the link by swiping down, and then will immediately re-select the entire text. The user generally cannot
// follow the link because it snaps back too quickly.
//
// On one iPhone 8, this did not reproduce until the device went to sleep, then it reliably reproduced.
import SwiftUI
let text = try! AttributedString(markdown: "Here is a link to [ArchiveOrg](https://archive.org). It should be selectable with the rotor without jumping back to the whole text.")
import Foundation
public class Disposable {
private var isDisposed = false
private let _dispose: () -> Void
public func dispose() {
if !isDisposed {
_dispose()
isDisposed = true
}
//
// TextStyle.swift
//
// Created by Rob Napier on 12/20/19.
// Copyright © 2019 Rob Napier. All rights reserved.
//
import SwiftUI
public struct TextStyle {
@rnapier
rnapier / doOnce.swift
Last active April 20, 2022 16:12
A function that only executes once. Good Swift or over-clever?
// Swift3 gets rid of dispatch_once and recommends replacing it with a lazy global.
// That's very straightforward when dispach_once is used to initialize something, but
// isn't an exact match when you want something to execute once, and then become a noop
// in a thread-safe way.
// The following approach seems completely "correct" and I guess actually a bit elegant,
// if by "elegant" you mean "terse and not immediately obvious to the reader, which makes
// you look very clever."
var doOnce: () -> Void = {
@rnapier
rnapier / observer.swift
Last active April 17, 2022 17:51
New ideas on Observer pattern in Swift
import UIKit
// Lots of ideas here that I'd love thoughts about. Some of this creates new highly generic types
// (UniqueIdentifier, IdentifiedSet) that may have broader purpose. Some of it defines a new Observer pattern.
// I've been playing around with this UniqueIdentifier type. Its purpose is to let you store things
// in dictionaries (or possibly sets) that you couldn't otherwise.
// It's just a self-referencial ObjectIdentifier. I used to use NSUUID for this purpose, but wondering
// if this is better.
@rnapier
rnapier / fix-xcode
Last active March 18, 2022 01:17
Links Xcode SDKs from the /SDKs directory (which you maintain yourself)
#!/usr/bin/python
# fix-xcode
# Rob Napier <robnapier@gmail.com>
# Script to link in all your old SDKs every time you upgrade Xcode
# Create a directory called /SDKs (or modify source_path).
# Under it, put all the platform directories:
# MacOSX.platform iPhoneOS.platform iPhoneSimulator.platform
# Under those, store the SDKs: