Skip to content

Instantly share code, notes, and snippets.

View GalCohen's full-sized avatar

Gal Cohen GalCohen

View GitHub Profile
import SwiftUI
import AsyncAlgorithms
struct AsyncChanges<V>: ViewModifier where V : Equatable, V: Sendable {
typealias Element = (oldValue: V, newValue: V)
typealias Action = (AsyncStream<Element>) async -> Void
@State private var streamPair = AsyncStream<Element>.makeStream()
private let action: Action
private let value: V
@HarshilShah
HarshilShah / CycledAnimationTimelineView.swift
Created April 29, 2023 05:17
A SwiftUI view that performs a looping animation in whole cycles. When the animation is disabled, it drives the current loop to completion, and pauses only then
struct CycledAnimationTimelineView<Content: View>: View {
var duration: Double
var isAnimating: Bool
@ViewBuilder var content: (Double) -> Content
@State private var isActuallyAnimating = false
@State private var startDate: Date?
var body: some View {
TimelineView(.animation(paused: !isActuallyAnimating)) { context in
//
// Copyright (c) Nathan Tannar
//
import SwiftUI
import Engine // https://github.com/nathantannar4/Engine
import Turbocharger // https://github.com/nathantannar4/Turbocharger
import Transmission // https://github.com/nathantannar4/Transmission
#if os(iOS)
@PimCoumans
PimCoumans / AnimationSequece.swift
Last active May 21, 2024 15:12
Simple way to chain and group multiple UIView animations
import UIKit
protocol StepAnimatable {
/// Start a sequence where you add each step in the `addSteps` closure. Use the provided `AnimationSequence` object
/// to add each step which should either be an actual animation or a delay.
/// The `completion` closure is executed when the last animation has finished.
/// - Parameters:
/// - addSteps: Closure used to add steps to the provided `AnimationSequence` object
/// - completion: Executed when the last animation has finished.
import Foundation
import Combine
extension Timer {
static func publish(at date: Date, tolerance: TimeInterval? = nil, on runLoop: RunLoop, in mode: RunLoop.Mode, options: RunLoop.SchedulerOptions? = nil) -> AnyPublisher<Date, Never> {
let subject = PassthroughSubject<Date, Never>()
let timer = Timer(fire: date, interval: 0, repeats: false) { _ in
subject.send(Date())
subject.send(completion: .finished)
@atierian
atierian / AsyncToCompletionHandlers.swift
Created November 8, 2021 16:41
Going from async to completion handlers.
import UIKit
enum SomeError: Error {
case foo, bar, baz, unknown
}
struct SDK {
func simpleAsync() async -> Int {
try? await Task.sleep(seconds: 2)
return 42
@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 / View+Discover.swift
Last active February 13, 2024 08:00
SwiftUI: discover underlying components to fill in gaps in SwiftUI api
import SwiftUI
extension View {
public func discover<T: UIView>(
tag: Int = .random(in: (.min)...(.max)),
where predicate: @escaping (T) -> Bool = { _ in true },
_ closure: @escaping (T) -> Void
) -> some View {
self.overlay(
DiscoveryView(tag: tag)
@IanKeen
IanKeen / View+Relative.swift
Last active January 16, 2023 13:03
SwiftUI relative frame
extension View {
func relative(width: CGFloat? = nil, height: CGFloat? = nil, alignment: Alignment = .center) -> some View {
Color.clear
.frame(maxWidth: width.map { _ in .infinity }, maxHeight: height.map { _ in .infinity })
.overlay(GeometryReader { proxy in
ZStack {
self.frame(
width: width.map { proxy.size.width * $0 },
height: height.map { proxy.size.height * $0 }
)