Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

View IanKeen's full-sized avatar
🏂

Ian Keen IanKeen

🏂
View GitHub Profile
@IanKeen
IanKeen / UserDefaultsKey.swift
Last active July 9, 2022 17:31
Simple type safe wrapper around UserDefaults
struct UserDefaultsKey<T: Codable> {
var name: String
var `default`: T
}
extension UserDefaults {
func get<T>(_ key: UserDefaultsKey<T>) -> T {
guard
let data = data(forKey: key.name),
let box = try? JSONDecoder().decode(Box<T>.self, from: data)
@IanKeen
IanKeen / AnyCodable.swift
Last active August 8, 2023 22:02
AnyCodable
public struct AnyCodable: Codable {
public var base: Any
public init(_ base: Any) {
self.base = base
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
guard !container.decodeNil() else {
@IanKeen
IanKeen / Namespace.swift
Created December 18, 2021 03:46
Namespace and Implicit member chains
// 1. Create a generic namespace we can ue to 'hang' values off
public struct Namespace<Base> { }
// 2. Add a namespace to a type(s) with the desired name
extension Color {
public static var theme: Namespace<Self> { .init() }
}
extension Font {
public static var theme: Namespace<Self> { .init() }
}
@IanKeen
IanKeen / Example.swift
Last active August 2, 2023 21:07
ObservableObjectContainer: Consolidate nested/child ObservableObjects into a single publisher, useful for 'parent' ObservableObjects
// Setup
class Child: ObservableObject {
@Published var value = ""
}
class Parent: ObservableObjectContainer {
let single = Child()
let array = [Child(), Child()]
func updateSingle() {
@IanKeen
IanKeen / .swift
Last active October 14, 2021 00:08
SwiftUI: quick and dirty nested ForEach debugger
import SwiftUI
struct Location: Equatable {
var file: String
var line: UInt
}
private struct ForEachKey: EnvironmentKey {
static var defaultValue: [Location] = []
}
private extension EnvironmentValues {
@IanKeen
IanKeen / TopLevelDecoder+Nested.swift
Created September 18, 2021 21:44
Decode an object nested under a key
extension TopLevelDecoder {
func decode<T: Decodable>(_ type: T.Type, from input: Input, under: String) throws -> T {
let decoder = try decode(_Decoder.self, from: input).decoder
let container = try decoder.container(keyedBy: AnyCodingKey.self)
return try container.decode(T.self, forKey: .init(under))
}
}
private struct _Decoder: Decodable {
var decoder: Decoder
@IanKeen
IanKeen / Require.swift
Last active September 11, 2021 18:49
SwiftUI: Conditional views from optional bindings with required constraints
public struct Require<Content: View>: View {
@StateObject private var registrar: ViewRegistrar
@ViewBuilder private var content: () -> Content
public init(_ value: Int, @ViewBuilder content: @escaping () -> Content) {
self._registrar = .init(wrappedValue: ViewRegistrar(limit: value))
self.content = content
}
public var body: some View {
@IanKeen
IanKeen / FocusState.swift
Last active June 30, 2023 17:00
SwiftUI: FocusedState shim for < iOS15
import Combine
import SwiftUI
extension View {
public func focused<T>(file: StaticString = #file, _ state: FocusState<T>, equals value: T) -> some View {
modifier(FocusedModifier(state: state, id: value, file: file))
}
}
@propertyWrapper
@IanKeen
IanKeen / EnvironmentValues.swift
Last active January 5, 2024 08:49
SwiftUI: Peek at/extract hidden environment values
import Foundation
import SwiftUI
extension EnvironmentValues {
public func value<T>(_: T.Type = T.self, forKey key: String) -> T? {
guard let value = first(where: { name($0, equals: key) }) else {
print("No EnvironmentValue with key '\(key)' found.")
return nil
}
@IanKeen
IanKeen / LoadingIndicator.swift
Last active August 19, 2021 23:25
SwiftUI: Drop-in Pull to Refresh mechanism
public struct LoadingIndicator: View {
@State private var startingOffset: CGFloat = 0
@State private var space: CGSize = .zero
@State private var size: CGSize = .zero
@State private var progress: Double = 0
@Binding private var isLoading: Bool {
didSet {
if isLoading { action() }
else { progress = 0 }
}