Skip to content

Instantly share code, notes, and snippets.

View ollieatkinson's full-sized avatar

Oliver Atkinson ollieatkinson

View GitHub Profile
@ollieatkinson
ollieatkinson / Tuple.swift
Last active April 22, 2024 15:13
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
Created February 7, 2024 10:40
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 November 5, 2022 18:39
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
@ollieatkinson
ollieatkinson / CombineLatestCollection.swift
Last active June 29, 2021 13:36
`combineLatest()` on `Collection` where elements are Publishers
import Combine
import Foundation
extension Collection where Element: Publisher {
public func combineLatest() -> CombineLatestCollection<Self> {
CombineLatestCollection(self)
}
}
@ollieatkinson
ollieatkinson / Decodable+ContainerType.swift
Last active June 19, 2021 10:21
Encoding / Decoding Container Types
enum DecodingContainer: String {
case keyed
case unkeyed
case singleValue
}
extension Decodable {
static var container: DecodingContainer {
do {