Skip to content

Instantly share code, notes, and snippets.

View IanKeen's full-sized avatar
🏂

Ian Keen IanKeen

🏂
View GitHub Profile
@IanKeen
IanKeen / Example_Complex.swift
Last active July 22, 2024 19:05
PropertyWrapper: @transaction binding for SwiftUI to make changes to data supporting commit/rollback
struct User: Equatable {
var firstName: String
var lastName: String
}
@main
struct MyApp: App {
@State var value = User(firstName: "", lastName: "")
@State var showEdit = false
@IanKeen
IanKeen / View+Discover.swift
Last active July 22, 2024 04:23
SwiftUI: discover underlying components to fill in gaps in SwiftUI api
import SwiftUI
extension View {
public func discover<T: UIView>(
where predicate: @escaping (T) -> Bool = { _ in true },
_ closure: @escaping (T) -> Void
) -> some View {
overlay(
DiscoveryView(predicate: predicate, setup: closure)
.frame(width: 0, height: 0)
@IanKeen
IanKeen / AnalyticsReducer.swift
Created January 16, 2024 04:27
TCA: Example of creating an Analytics component to get before/after state
public protocol AnalyticsReducer {
associatedtype State
associatedtype Action
func analytics(before: State, after: State, action: Action) -> Effect<Action>
}
public struct _AnalyticsReducer<Base: Reducer, Analytics: AnalyticsReducer>: Reducer where Analytics.State == Base.State, Analytics.Action == Base.Action {
@usableFromInline
let base: Base
@IanKeen
IanKeen / EntryPoint.swift
Last active July 8, 2024 06:25
Example main.swift
import Foundation
import SwiftUI
let isUITesting = /* your UI test detection here */
@main
struct EntryPoint {
static func main() {
if isUITesting {
UITestApp.main()
@IanKeen
IanKeen / Default.swift
Last active July 4, 2024 14:55
PropertyWrapper: Decode default values. when they are `null`
import Foundation
public protocol DefaultValue {
associatedtype Value: Codable
static var value: Value { get }
}
@propertyWrapper
public struct Default<Default: DefaultValue>: Codable {
@IanKeen
IanKeen / AsyncPublished.swift
Created May 21, 2024 17:58
PropertyWrapper: AsyncPublished
@propertyWrapper @MainActor public struct AsyncPublished<Value> {
public typealias AsyncAction = (Value) async throws -> Void
private class State {
var wrappedValue: Value
var isWorking: Bool = false
var current: Task<Void, Never>?
var action: AsyncAction = { _ in fatalError("Please configure action in parent object") }
init(wrappedValue: Value) {
@IanKeen
IanKeen / .swift
Created July 26, 2022 22:33
SwiftUI: @StateObject.init(wrappedValue:) gotcha
struct Parent: View {
@State private var foo = "foo" {
didSet { print("Parent", foo) }
}
var body: some View {
VStack {
Inner(value: foo)
Button("Parent Double") {
@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 June 26, 2024 07:38
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 / Require.swift
Last active June 26, 2024 07:38
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 {