Skip to content

Add SwiftUI-style animation, transitions, and content transitions#528

Open
zxss702 wants to merge 80 commits intomoreSwift:mainfrom
zxss702:add-animation
Open

Add SwiftUI-style animation, transitions, and content transitions#528
zxss702 wants to merge 80 commits intomoreSwift:mainfrom
zxss702:add-animation

Conversation

@zxss702
Copy link
Copy Markdown

@zxss702 zxss702 commented Apr 28, 2026

Summary

This PR adds a SwiftUI-aligned animation system to SwiftCrossUI, covering core animation types, transactions, animated view modifiers, transitions, content transitions, PhaseAnimator, KeyframeAnimator, backend rendering hooks, and an animation example app.

The implementation is based on SwiftUI’s model: state changes produce transactions, transactions carry animation intent, the view graph schedules updates and render frames, and backends only apply the current presentation value for each frame. This keeps animation behavior in SwiftCrossUI’s view graph instead of pushing animation policy into each backend.

Motivation

Before this PR, SwiftCrossUI could update layout and state, but it did not have a unified animation pipeline comparable to SwiftUI. That made common SwiftUI patterns hard to express:

  • animating state changes with transaction context
  • using .animation(..., value:) and withAnimation
  • animating opacity, offset, scale, rotation, blur, and transform effects
  • animating insertion/removal through .transition(...)
  • animating text/content changes with .contentTransition(...)
  • using PhaseAnimator and KeyframeAnimator
  • preserving layout identity during animated updates
  • supporting backend-specific presentation effects such as blur and transforms

This PR fills that gap while preserving SwiftCrossUI’s existing layout and backend architecture.

SwiftUI Alignment

This PR intentionally follows SwiftUI naming and behavior where practical:

  • Adds SwiftUI-style animation primitives: Animation, CustomAnimation, UnitCurve, Spring, VectorArithmetic, Animatable, AnimatablePair, and EmptyAnimatableData.
  • Adds transaction-aware state mutation flow so animation intent travels with state changes.
  • Adds animation view modifiers and effect modifiers such as opacity, offset, scaleEffect, rotationEffect, transformEffect, blur(radius:opaque:), and zIndex.
  • Adds SwiftUI-style transitions through Transition, AnyTransition, TransitionPhase, and built-in transitions.
  • Adds .blurReplace, .push(from:), slide behavior, insertion/removal phase handling, and support for multiple simultaneous removal transitions.
  • Adds content transitions, including text/numeric text transitions.
  • Adds PhaseAnimator and KeyframeAnimator APIs.
  • Adds Angle.zero, non-uniform scaleEffect(x:y:anchor:), and blur(radius:opaque:) for source compatibility with SwiftUI-style code.

Some behavior is intentionally best-effort where backend capabilities differ. For example, blur(radius:opaque:) accepts the SwiftUI-compatible opaque parameter, but current backend blur APIs do not expose an opaque edge-sampling mode, so that flag is preserved for API compatibility and ignored internally for now.

State And Transaction Model

The state system now participates in animation transactions:

  • State writes can carry the active transaction.
  • Binding writes preserve transaction context.
  • TransactionContext and StateMutationContext make implicit and explicit animations flow through graph updates.
  • Publisher-driven updates are scheduled on the backend UI thread and throttled through the graph update host.
  • Observable / Perceptible tracking is integrated with the transaction-aware update path.
  • View model observations enqueue graph mutations instead of forcing immediate layout updates.

This is important because SwiftUI animation behavior is not just a visual effect. It depends on when and why state changes happen. By moving animation intent through transactions, SwiftCrossUI can animate state-driven updates consistently.

View Graph And Render Scheduling

This PR adds a graph-owned update scheduler:

  • GraphUpdateHost batches state and observation mutations.
  • Render frames are requested through the environment.
  • Interrupted transactions can requeue remaining render frames.
  • Render-frame layout disables layout probing/caching where needed so animation frames do not incorrectly redistribute space.
  • Animation frame timing uses backend-preferred frame rates, with a default of 60 FPS.
  • The implementation was updated to align with the newer BaseAppBackend / FullAppBackend / BackendFeatures.* protocol split.

This keeps animation scheduling centralized and avoids making each backend responsible for deciding graph dirtiness or animation lifecycle.

Layout Identity And Stability

Animation exposes layout identity problems, especially around conditional views, ForEach, and transitions. This PR adds layout infrastructure to make animated updates stable:

  • Adds LayoutInputKey and layout generation tracking.
  • Adds layout input keys to core views and modifiers.
  • Improves stack layout cache invalidation.
  • Prevents stale ForEach child indices during animated transitions.
  • Supports identity reset probes and transition identity handling.
  • Removes unused transition/proposed-size state that no longer contributed to layout correctness.

The goal is to avoid reusing layout or graph state when the logical view identity has changed, while still allowing stable reuse when it is correct.

Transitions

The PR adds transition infrastructure for insertion and removal:

  • Transition, AnyTransition, TransitionPhase, and built-in transition implementations.
  • Dynamic transition state management for views entering and leaving the hierarchy.
  • Support for multiple simultaneous removals.
  • Correct insertion/removal direction handling for slide and push transitions.
  • blurReplace transition support.
  • Transition tests for insertion/removal behavior.

Usage example:

if isVisible {
    Text("Saved")
        .transition(.blurReplace)
}

withAnimation(.easeInOut) {
    isVisible.toggle()
}

Content Transitions

The PR adds content transition support, including text-specific transitions:

  • ContentTransition API.
  • Numeric text transition support.
  • Text layout fragments so text changes can animate at character/grapheme level when the backend can provide native layout fragments.
  • Whole-view fallback when precise text fragments are unavailable.
  • Backend hooks for text layout fragments, with a safe default returning nil.

Usage example:

Text("\(count)")
    .contentTransition(.numericText(value: Double(count)))

withAnimation(.spring()) {
    count += 1
}

I did my best to mimic SwiftUI. However—perhaps due to a flaw in my design approach—numericText suffers from poor performance when handling lengthy content. Theoretically, it should support overlapping animations; yet, precisely because of these performance issues, such overlaps do occur. Consequently, this API is essentially just for show.

PhaseAnimator And KeyframeAnimator

This PR adds SwiftUI-style phase and keyframe animation tools:

  • PhaseAnimator cycles through phase values and now correctly advances through all phases when triggered.
  • KeyframeAnimator supports keyframe tracks and combines them into one root timeline.
  • Keyframe and phase animation examples are included in the animation showcase.
  • Tests cover phase triggering and keyframe timeline composition.

Usage example:

PhaseAnimator([0, 1, 2], trigger: trigger) { phase in
    Text("Phase \(phase)")
        .scaleEffect(phase == 1 ? 1.2 : 1.0)
}

Backend Support

Animation rendering is wired through backend-facing APIs instead of hardcoding platform behavior in views:

  • Adds backend hooks for opacity, transform, blur, visibility, z-index, and preferred frame rate.
  • Adds BackendFeatures.ViewEffects to the backend feature model.
  • AppKit, UIKit, GTK, GTK3, Android, WinUI, DummyBackend, and DefaultBackend paths are updated where relevant.
  • Android gains animation and blur support.
  • WinUI gains composition-backed blur support through a dedicated WinUI interop implementation.
  • WinUI blur code was refined with deferred install and layer visual handling.
  • Backend refresh-rate handling was corrected for low-Hz displays.

WinUI Interop

The previous placeholder C++ file is replaced with a real WinUI composition interop implementation:

  • Adds WinUIInterop.cpp.
  • Adds WinUI interop declarations in the public header.
  • Uses manually declared ABI pieces needed for composition-backed blur.
  • Keeps the interop boundary narrow and documented.

It is worth noting that, out of laziness, I did not update the swift-winui library within WinUI; instead, I simply copied out the API headers. Theoretically, I should have updated swift-winui.

Examples And Documentation

This PR adds an AnimationExample app and updates documentation references:

  • Animation showcase.
  • Animation track section.
  • Transition showcase.
  • Timeline showcase.
  • Transaction binding section.
  • Content transition section.
  • Identity reset and state tile probes.
  • Keyframe and phase animation examples.
  • Documentation link to the new animation example.

The example is intended to exercise real workflows rather than only demonstrate isolated APIs.

Tests

This PR adds and updates coverage for:

  • Core animation declarations compiling.
  • Unit curve and repeated animation sample values.
  • Keyframe track composition.
  • Triggered PhaseAnimator advancing through all phases.
  • Transition behavior.
  • ForEach animated transition stability.
  • Publisher UI update throttling.
  • Binding transaction propagation.

Validation run locally:

  • swift build --target SwiftCrossUI
  • swift build --target SwiftCrossUITests
  • swift build --package-path Examples --target AnimationExample
  • swift test --skip-build --filter SwiftCrossUITests

The animation-related tests pass. On my machine, the full filtered test run still reports the existing AppKitBackend dimension mismatch where the expected size is 92x96 and the local result is 102x104; this appears to be a local AppKit text/layout metric difference rather than an animation regression.

Notes For Reviewers

The largest conceptual change is that animation is now graph- and transaction-driven. Backends should remain mostly presentation executors: they apply opacity, transform, blur, z-index, widget size, and position for the current frame, but they do not own animation state or decide graph update scheduling.

Review focus areas:

  • transaction propagation through state, binding, publisher, and observation updates
  • graph update batching and render-frame scheduling
  • layout cache invalidation with LayoutInputKey
  • transition identity and simultaneous removal behavior
  • backend effect implementations, especially blur and transform behavior
  • SwiftUI API naming/source compatibility

AI Usage Statement

  • The data models within the Animation directory—including animation curves (Spring.swift) and built-in Transition presets (such as MoveTransition)—were written entirely by hand.
  • All code comments were translated into English by Codex. // I did not independently verify the accuracy of these translations, as my English proficiency is quite limited.
  • The modifications within WinUIBackend were implemented by Codex; since I am not particularly familiar with WinUI, I simply verified that the code was "functional."
  • The entire contents of AnimationExample were written by Codex; I highly recommend adding animation support to the other examples as well.
  • Some modifications to various View components were performed by Codex—for instance, the mechanical addition of LayoutInputKey support.

In practice, I utilized Codex to analyze the OpenSwiftUI codebase; I did not independently verify whether the architectural concepts and approaches provided to me by Codex regarding OpenSwiftUI were technically correct. However, based on my current understanding, the implementation appears to be largely aligned with the official SwiftUI framework.


The introductory summary for this PR was also translated using Codex. I subsequently used Google Translate to translate it back into Chinese for verification, and I can confirm that the PR summary is free of errors.

s-k and others added 30 commits May 4, 2026 11:43
Views now update automatically when an `@Observable` model class used
inside `body` changes. The same is true for `@Perceptible`.

Adds a `@Bindable` property wrapper so that properties of observable
models can be easily used as bindings.
zxss702 added 25 commits May 4, 2026 11:50
@zxss702 zxss702 changed the title Add animation Add SwiftUI-style animation, transitions, and content transitions May 4, 2026
@zxss702 zxss702 marked this pull request as ready for review May 4, 2026 04:51
Copilot AI review requested due to automatic review settings May 4, 2026 04:51
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a graph-driven SwiftUI-style animation system to SwiftCrossUI, spanning animation primitives, transactions, transitions, content transitions, animators, and backend presentation hooks. It fits into the core rendering architecture by moving animation policy into the view graph and transaction pipeline instead of individual backends.

Changes:

  • Adds core animation/transaction APIs (Animation, Transaction, transitions, content transitions, PhaseAnimator, KeyframeAnimator, animatable protocols/types).
  • Wires transaction-aware scheduling and presentation updates through the view graph, state system, and multiple backends.
  • Adds tests, example apps, and docs for transitions, observable models, and animation showcases.

Reviewed changes

Copilot reviewed 131 out of 132 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
Tests/SwiftCrossUITests/TransitionTests.swift Adds regression coverage for optional-view transition wrapping.
Tests/SwiftCrossUITests/PublisherTests.swift Adds coverage for default ObservableObject publisher stability.
Sources/WinUIInterop/include/WinUIInterop.h Declares WinUI interop APIs for refresh rate and blur.
Sources/WinUIInterop/dummy.cpp Removes previous placeholder WinUI interop source.
Sources/UIKitBackend/UIKitBackend.swift Exposes preferred frame rate for animation scheduling.
Sources/UIKitBackend/UIKitBackend+Passive.swift Adds UIKit text layout fragment extraction.
Sources/UIKitBackend/UIKitBackend+Container.swift Adds UIKit effect setters for opacity/transform/visibility/z-order.
Sources/SwiftCrossUI/_App.swift Integrates app root with graph update host and observation-driven refresh.
Sources/SwiftCrossUI/Views/_BuiltinPickerImplementation.swift Reduces redundant picker updates and caches selected/options state.
Sources/SwiftCrossUI/Views/VStack.swift Adds layout input key support for stack cache invalidation.
Sources/SwiftCrossUI/Views/TupleView.swift.gyb Adds layout state plumbing and transition trait forwarding for tuple views.
Sources/SwiftCrossUI/Views/ToggleSwitch.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/ToggleButton.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/TextField.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/Spacer.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/Slider.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/SecureField.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/ScrollView.swift Adjusts scroll view sizing/alignment logic.
Sources/SwiftCrossUI/Views/ProgressView.swift Adds layout input keys for progress-related views.
Sources/SwiftCrossUI/Views/OptionalView.swift Reworks optional child handling onto dynamic transition state.
Sources/SwiftCrossUI/Views/Modifiers/ViewModifier.swift Introduces ViewModifier, ModifiedContent, and placeholder content views.
Sources/SwiftCrossUI/Views/Modifiers/TransactionModifier.swift Adds .transaction and .animation(..., value:) view modifiers.
Sources/SwiftCrossUI/Views/Modifiers/Layout/PaddingModifier.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/Modifiers/Layout/FrameModifier.swift Adds layout input key support for frame modifiers.
Sources/SwiftCrossUI/Views/Modifiers/Effects/OpacityModifier.swift Adds animatable opacity effect view.
Sources/SwiftCrossUI/Views/Menu.swift Adds layout input key support for menu buttons.
Sources/SwiftCrossUI/Views/IDView.swift Adds explicit identity wrapper with transition-aware replacement handling.
Sources/SwiftCrossUI/Views/HStack.swift Adds layout input key support for horizontal stacks.
Sources/SwiftCrossUI/Views/Group.swift Adds layout input key support for groups.
Sources/SwiftCrossUI/Views/EmptyView.swift Adds layout input key support for empty views.
Sources/SwiftCrossUI/Views/EitherView.swift Reworks conditional view switching onto dynamic transition state.
Sources/SwiftCrossUI/Views/DynamicTransitionIdentity.swift Defines transition identity model.
Sources/SwiftCrossUI/Views/DynamicTransitionContent.swift Defines transition content payload.
Sources/SwiftCrossUI/Views/Checkbox.swift Adds layout input key support.
Sources/SwiftCrossUI/Views/Button.swift Adds layout input key support for buttons.
Sources/SwiftCrossUI/Views/AnyView.swift Improves child widget replacement when erased child type changes.
Sources/SwiftCrossUI/ViewGraph/ViewGraph.swift Injects graph update host into root graph environment.
Sources/SwiftCrossUI/ViewGraph/ErasedViewGraphNode.swift Exposes layout-preparation and identity/generation hooks.
Sources/SwiftCrossUI/ViewGraph/AnyViewGraphNode.swift Adds type-erased layout-preparation and identity APIs.
Sources/SwiftCrossUI/Values/UnitPoint.swift Adds unit-space anchor type used by effects/transitions.
Sources/SwiftCrossUI/Values/Path.swift Adds non-uniform affine scaling helper.
Sources/SwiftCrossUI/Values/Color/Color.swift Adds layout input key support for color views.
Sources/SwiftCrossUI/Values/Angle.swift Adds SwiftUI-style angle value type.
Sources/SwiftCrossUI/SwiftCrossUI.docc/Examples.md Documents the new animation example app.
Sources/SwiftCrossUI/State/ViewModelObserver.swift Adds observation helper protocol for view/body recomputation.
Sources/SwiftCrossUI/State/StateImpl.swift Makes state reads/writes transaction-aware and dependency-tracked.
Sources/SwiftCrossUI/State/State.swift Extends State support for Observation/Perception-backed models.
Sources/SwiftCrossUI/State/Publisher.swift Preserves transaction context in throttled UI updates.
Sources/SwiftCrossUI/State/Published.swift Makes published bindings and sends transaction-aware.
Sources/SwiftCrossUI/State/ObservableObject.swift Reworks default ObservableObject publisher storage/caching.
Sources/SwiftCrossUI/State/Locations/Location.swift Adds transaction/update/render thread-local contexts.
Sources/SwiftCrossUI/State/Binding.swift Adds transaction-carrying bindings and binding animation helpers.
Sources/SwiftCrossUI/State/Bindable.swift Introduces @Bindable for model-backed bindings.
Sources/SwiftCrossUI/State/AppStorage/AppStorage.swift Adds dependency-read tracking for app storage state.
Sources/SwiftCrossUI/Scenes/WindowReference.swift Routes window scene updates through graph update host and observation.
Sources/SwiftCrossUI/Layout/StackLayoutCache.swift Adds cache signature for layout-input-based invalidation.
Sources/SwiftCrossUI/Layout/LayoutInputKey.swift Introduces layout input key/fingerprint infrastructure.
Sources/SwiftCrossUI/Environment/EnvironmentValues.swift Adds render-frame request and graph update host environment hooks.
Sources/SwiftCrossUI/Backend/BaseAppBackend.swift Requires view-effect backend feature support.
Sources/SwiftCrossUI/Backend/BackendFeatures/ViewEffects.swift Defines backend effect API surface.
Sources/SwiftCrossUI/Backend/BackendFeatures/PassiveViews/TextViews.swift Adds text fragment API for content transitions.
Sources/SwiftCrossUI/Backend/BackendFeatures/Core/Core.swift Adds preferred FPS API for backends.
Sources/SwiftCrossUI/Animation/Transition/TransitionPhase.swift Defines transition phases and properties.
Sources/SwiftCrossUI/Animation/Transition/Transition.swift Adds transition protocol and composition helpers.
Sources/SwiftCrossUI/Animation/Transition/ContentTransition.swift Adds content transition API including numeric text mode.
Sources/SwiftCrossUI/Animation/Transition/BuiltinTransitions.swift Implements built-in transitions and transition combinators.
Sources/SwiftCrossUI/Animation/Transition/AnyTransition.swift Adds type-erased transition model and transition modifier.
Sources/SwiftCrossUI/Animation/Transaction/TransactionEnvironment.swift Adds branch/current transaction environment handling.
Sources/SwiftCrossUI/Animation/Transaction/TransactionContext.swift Adds withTransaction/withAnimation helpers.
Sources/SwiftCrossUI/Animation/Transaction/Transaction.swift Defines transaction payload and animation completion support.
Sources/SwiftCrossUI/Animation/Runtime/PresentationAnimation.swift Adds presentation-value animator for frame-based interpolation.
Sources/SwiftCrossUI/Animation/Runtime/LayoutPresentationStore.swift Stores animated layout positions across frames.
Sources/SwiftCrossUI/Animation/Runtime/AnimatableEffectChildren.swift Adds shared child storage for animatable effect views.
Sources/SwiftCrossUI/Animation/Core/UnitCurve.swift Adds timing-curve implementation.
Sources/SwiftCrossUI/Animation/Core/TimelineSchedule.swift Adds timeline scheduling types.
Sources/SwiftCrossUI/Animation/Core/Spring.swift Adds spring model and spring math helpers.
Sources/SwiftCrossUI/Animation/Core/PhaseAnimator.swift Adds SwiftUI-style phase animator view.
Sources/SwiftCrossUI/Animation/Core/KeyframesBuilder.swift Adds result builders for keyframe APIs.
Sources/SwiftCrossUI/Animation/Core/CustomAnimation.swift Defines custom animation protocol.
Sources/SwiftCrossUI/Animation/Core/BuiltinAnimations.swift Implements built-in curve/spring/delay/repeat animation wrappers.
Sources/SwiftCrossUI/Animation/Core/AnimationState.swift Adds animation-local state/context storage.
Sources/SwiftCrossUI/Animation/Core/AnimationCompletionCriteria.swift Defines animation completion criteria.
Sources/SwiftCrossUI/Animation/Core/Animation.swift Adds main animation value type and factory methods.
Sources/SwiftCrossUI/Animation/Animatable/VectorArithmetic.swift Adds vector arithmetic and animatable conformances.
Sources/SwiftCrossUI/Animation/Animatable/EmptyAnimatableData.swift Adds empty animatable data type.
Sources/SwiftCrossUI/Animation/Animatable/AnimatableValues.swift Adds single-value animatable container.
Sources/SwiftCrossUI/Animation/Animatable/AnimatablePair.swift Adds animatable pair type.
Sources/SwiftCrossUI/Animation/Animatable/Animatable.swift Adds animatable protocol and ignored wrapper.
Sources/GtkCHelpers/gtk_custom_root_widget.c Adjusts GTK root widget natural sizing behavior.
Sources/Gtk3Backend/Gtk3Backend.swift Adds GTK text layout fragment extraction.
Sources/DummyBackend/DummyBackend.swift Adds stored effect state for animation tests.
Sources/AndroidBackend/Kotlin/AndroidBackendHelpers.kt Adds Android helpers for FPS, main-thread dispatch, and text fragments.
Sources/AndroidBackend/AndroidBackendHelpers.swift Exposes new Android helper methods to Swift.
Sources/AndroidBackend/AndroidBackend.swift Adds Android FPS/effect/text-fragment support and safer sizing.
Package.swift Adds swift-perception and WinUIInterop dependency wiring.
Package.resolved Resolves new root package dependencies.
Examples/Sources/ObservableExample/ObservableModel.swift Adds perceptible observable example model.
Examples/Sources/ObservableExample/ObservableApp.swift Adds example app demonstrating @Bindable/observable models.
Examples/Sources/AnimationExample/TransitionShowcaseSection.swift Adds transition demo UI.
Examples/Sources/AnimationExample/TransitionItem.swift Adds transition demo item model.
Examples/Sources/AnimationExample/TransactionBindingSection.swift Adds transaction/binding animation demo UI.
Examples/Sources/AnimationExample/TimelineShowcaseSection.swift Adds phase/keyframe animation demo UI.
Examples/Sources/AnimationExample/ScaleFadeModifier.swift Adds custom modifier used in transition demo.
Examples/Sources/AnimationExample/PivotTransition.swift Adds custom transition used in demo.
Examples/Sources/AnimationExample/MotionPhase.swift Adds phase data for phase animator demo.
Examples/Sources/AnimationExample/KeyframeProbeValue.swift Adds animatable value used by keyframe demo.
Examples/Sources/AnimationExample/IdentityStateTile.swift Adds .id() reset demo tile.
Examples/Sources/AnimationExample/IdentityResetProbe.swift Adds identity reset transition demo.
Examples/Sources/AnimationExample/ContentTransitionSection.swift Adds content transition demo UI.
Examples/Sources/AnimationExample/AnimationTrackSection.swift Adds implicit/scoped animation demo UI.
Examples/Sources/AnimationExample/AnimationShowcaseView.swift Assembles the animation showcase screen.
Examples/Sources/AnimationExample/AnimationPreset.swift Defines animation presets for the example app.
Examples/Sources/AnimationExample/AnimationApp.swift Adds new animation example executable entrypoint.
Examples/Package.swift Registers animation and observable example targets/dependencies.
Examples/Package.resolved Resolves example package dependencies.
Examples/Bundler.toml Adds bundler entries for new example apps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/SwiftCrossUI/Animation/Transition/BuiltinTransitions.swift
Comment thread Sources/SwiftCrossUI/Animation/Transition/BuiltinTransitions.swift
Comment on lines +171 to +193
public func value<V: Animatable>(
fromValue: V,
toValue: V,
initialVelocity: V,
time: TimeInterval
) -> V {
var value = fromValue
let delta = toValue.animatableData - fromValue.animatableData
value.animatableData = fromValue.animatableData + self.value(target: delta, time: time)
return value
}

public func velocity<V: Animatable>(
fromValue: V,
toValue: V,
initialVelocity: V,
time: TimeInterval
) -> V {
var value = fromValue
value.animatableData = self.velocity(
target: toValue.animatableData - fromValue.animatableData,
time: time
)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +96 to +112
func publisher(for object: any ObservableObject) -> Publisher {
let key = ObjectIdentifier(object)

lock.lock()
if let entry = entries[key], entry.owner != nil {
let publisher = entry.publisher
lock.unlock()
return publisher
}
lock.unlock()

let entry = makeEntry(for: object)

lock.lock()
entries = entries.filter { $0.value.owner != nil }
entries[key] = entry
lock.unlock()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants