Skip to content

Instantly share code, notes, and snippets.

View ollieatkinson's full-sized avatar
🪐

Oliver Atkinson ollieatkinson

🪐
View GitHub Profile
@ollieatkinson
ollieatkinson / Result+SharedStore.swift
Last active August 16, 2024 11:11
A store type with support for sharing, caching, invalidating and streaming `Result` values from `source`
extension Result where Success: Sendable, Failure == Error {
actor SharedStore {
typealias ID = UInt
private let source: AsyncStream<Result>
private let cancellingGracePeriod: Duration
private let clock: ContinuousClock
@ollieatkinson
ollieatkinson / URLDecoder.swift
Created May 22, 2024 20:16
Decoder for decoding URL into a concrete type
import Foundation
public final class URLDecoder: Decoder {
public var codingPath: [CodingKey] = []
public var userInfo: [CodingUserInfoKey: Any] = [:]
let parseParametersFromURL: (URL) throws -> [String: Any]
public init<Output>(_ regex: Regex<Output>) {
self.parseParametersFromURL = { url in
@ollieatkinson
ollieatkinson / Tuple.swift
Last active July 25, 2024 06:00
Implementation of `Tuple` type using Swift's new parameter packs
public struct Tuple<each T> {
public private(set) var value: (repeat each T)
public init(_ value: repeat each T) { self.value = (repeat each value) }
}
extension Tuple {
public func map<each U>(
_ transform: (repeat each T) throws -> (repeat each U)
) rethrows -> (repeat each U) {
@ollieatkinson
ollieatkinson / CGContextRepresentable.swift
Created February 20, 2024 09:19
Render to a CGContext directly from SwiftUI
protocol CGContextRepresentable: View {
func draw(in context: CGContext, frame: CGRect)
}
extension CGContextRepresentable {
var body: some View { _CGContextView(draw: draw) }
}
private struct _CGContextView: UIViewRepresentable {
let draw: (CGContext, CGRect) -> Void
@ollieatkinson
ollieatkinson / OnChangeObservable.swift
Last active May 15, 2024 06:08
OnChangeObservable property wrapper
@propertyWrapper
public struct OnChangeObservable<Value: Equatable> {
private var storage: Storage
public var wrappedValue: Value {
get { storage.value }
set { storage.value = newValue }
}
public var projectedValue: OnChangeObservable<Value> {
@ollieatkinson
ollieatkinson / CombineLatest.swift
Created August 1, 2022 08:40
CombineLatest for Swift Concurrency
public func combineLatest<C>(
_ collection: C,
bufferingPolicy limit: AsyncStream<[C.Element.Element]>.Continuation.BufferingPolicy = .unbounded
) -> AsyncStream<[C.Element.Element]> where C: Collection, C.Element: AsyncSequence {
AsyncStream(bufferingPolicy: limit) { continuation in
let stream = CombineLatestActor<C.Element.Element>(collection.count)
continuation.onTermination = { @Sendable termination in
switch termination {
case .cancelled: Task { await stream.cancel() }
case .finished: break
@ollieatkinson
ollieatkinson / AnyEquatable.swift
Last active February 20, 2024 13:28
Equatable `Any` using existential
public func isEqual(_ x: Any, _ y: Any) -> Bool {
if let isEqual = (x as? any Equatable)?.isEqual(to: y) {
return isEqual
} else if let equatable = x as? AnyEquatable {
return equatable.isEqual(to: y)
} else {
return (x as? any OptionalProtocol).isNil && (y as? any OptionalProtocol).isNil
}
}
@ollieatkinson
ollieatkinson / Navigation.swift
Last active March 3, 2022 18:16
NavigationRoute for Swift Composable Architecture
import ComposableArchitecture
import SwiftUI
public struct RouteIntent<R: NavigationRoute>: Hashable {
public enum Action: Hashable {
case navigateTo
case enterInto(EnterIntoContext = .default)
}
@ollieatkinson
ollieatkinson / Publishers+RetryDelay.swift
Last active June 10, 2024 11:26
Add a delay in-between each Combine retry, offering a timing function and default implementations for none, constant seconds and exponential backoff
import Combine
import Foundation
extension Publisher {
public func retry<S: Scheduler>(
_ max: Int = Int.max,
delay: Publishers.RetryDelay<Self, S>.TimingFunction,
scheduler: S
) -> Publishers.RetryDelay<Self, S> {
@ollieatkinson
ollieatkinson / Executable.swift
Created August 17, 2021 15:41
Simply execute shell commands from Swift
public struct Executable {
let url: URL
public init(_ filePath: String) {
url = URL(fileURLWithPath: filePath)
}
public init(_ url: URL) {
self.url = url