This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Built with Swift 6 (Xcode 16b1) | |
actor Accumulator { | |
static let shared = Accumulator() | |
var values: [String] = [] | |
// A couple of approaches, neither of which works. | |
func add(value: String) { values.append(value) } | |
nonisolated func addSync(value: String) { Task { await add(value: value) } } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Version of Swift 6 Mutex, with minimal API (just withLock), portable to at least iOS 15, probably much earlier. | |
// I cannot yet promise it's actually correct. | |
@frozen | |
public struct Mutex<Value> { | |
private let buffer: ManagedBuffer<Value, os_unfair_lock> | |
public init(_ initialValue: Value) { | |
buffer = ManagedBuffer<Value, os_unfair_lock>.create(minimumCapacity: 1) { _ in initialValue } | |
buffer.withUnsafeMutablePointerToElements { lockPtr in |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Some exploration into how selector-based notification interact with actors. | |
/// | |
/// Or in the words of Brent Simmons (@[email protected]), | |
/// "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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
public class Disposable { | |
private var isDisposed = false | |
private let _dispose: () -> Void | |
public func dispose() { | |
if !isDisposed { | |
_dispose() | |
isDisposed = true | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This GridView makes me cry. It is recreating an HTML-style bordered table, sized to | |
// its data, with a header. It requires a GeometryReader and Preferences, which might | |
// be unavoidable, but it also requires a *horrible* DispatchQueue.main.async in updateMaxValue. | |
// This means it doesn't work in Previews, and completely breaks the idea of "declarative" UI. | |
import SwiftUI | |
struct WidthPreferenceKey: PreferenceKey { | |
static var defaultValue: CGFloat = .zero | |
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct LengthLimitedTextField: UIViewRepresentable { | |
var title: String | |
@Binding var text: String | |
var maxLength: Int | |
var onCommit: () -> Void | |
init(_ title: String, text: Binding<String>, maxLength: Int = 255, onCommit: @escaping () -> Void) { | |
self.title = title | |
self._text = text | |
self.maxLength = maxLength |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on https://twitter.com/ravibastola/status/1249555595285291008?s=20 | |
extension Bundle { | |
// This is synchronous, which is bad if called on the main queue. | |
func decodeJSON<T: Decodable>(_ type: T.Type = T.self, from filename: String) throws -> T { | |
guard let path = self.url(forResource: filename, withExtension: nil) else { | |
throw NSError(domain: NSCocoaErrorDomain, | |
code: CocoaError.fileNoSuchFile.rawValue, | |
userInfo: [NSFilePathErrorKey: filename]) | |
} |
NewerOlder