This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 |
This file contains hidden or 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 { |
This file contains hidden or 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" | |
}, | |
{ |
This file contains hidden or 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 { |
This file contains hidden or 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 | |
protocol DataStorage { | |
subscript(identifier: String) -> Data? { get set } | |
} | |
extension UserDefaults: DataStorage { | |
subscript(identifier: String) -> Data? { | |
get { return data(forKey: identifier) } | |
set { set(newValue, forKey: identifier) } |
This file contains hidden or 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
// Fully type-erased solution for | |
// https://stackoverflow.com/questions/55549318/avoiding-type-erasure-when-implementing-the-repository-pattern/55550454 | |
// I don't like type-erasers like this; I believe it can be sliced a better way. | |
// Compare https://gist.github.com/rnapier/f7f0fa6202b0d6586af188635f54b28b, which I like, but relies on a common | |
// currency of serializing everything to Data and working with that instead of having storage that can deals with Element | |
// directly. | |
// FURTHER THOUGHTS: | |
// | |
// This example is interesting because, like so many of these toy projects, its design is completely broken and wouldn't |