View TestVO.swift
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.") |
View ValueStream.swift
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 | |
} |
View GridView.swift
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) { |
View LengthLimitedTextField.swift
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 |
View decodeJSON.swift
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]) | |
} |
View StyledText.swift
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 { |
View assertion.swift
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 |
View JSONStringConvertible.swift
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 protocol JSONStringConvertible: class { | |
var jsonString: String { get } | |
} | |
extension Logger { | |
// Converts an arbitrary object into some that is JSON-safe | |
static func makeJSONObject(_ object: Any) -> Any { | |
if let jsonObj = object as? JSONStringConvertible { |
View TypeCoder.swift
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 | |
/// Simple example of decoding different values based on a "type" field | |
let json = Data(""" | |
[{ | |
"type": "user", | |
"name": "Alice" | |
}, | |
{ |
View APIClient.swift
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 | |
// Provides a nice bare-init for ID types | |
protocol IDType: Codable, Hashable { | |
associatedtype Value | |
var value: Value { get } | |
init(value: Value) | |
} | |
extension IDType { |
NewerOlder