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 (@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. |
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]) | |
} |
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
// | |
// TextStyle.swift | |
// | |
// Created by Rob Napier on 12/20/19. | |
// Copyright © 2019 Rob Napier. All rights reserved. | |
// | |
import SwiftUI | |
public struct TextStyle { |
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
/// | |
/// Boring setup. See below for the good parts | |
/// | |
public class Logger { | |
public static let root = Logger(subsystem: .none, parent: nil) | |
public let subsystem: Subsystem | |
public let parent: Logger? | |
public init(subsystem: Subsystem, parent: Logger? = .root) { | |
self.subsystem = subsystem |
NewerOlder