Back to Skills

axiom-uikit-animation-debugging

verified

Use when CAAnimation completion handler doesn't fire, spring physics look wrong on device, animation duration mismatches actual time, gesture + animation interaction causes jank, or timing differs between simulator and real hardware - systematic CAAnimation diagnosis with CATransaction patterns, frame rate awareness, and device-specific behavior

View on GitHub

Marketplace

axiom-marketplace

CharlesWiltgen/Axiom

Plugin

axiom

Repository

CharlesWiltgen/Axiom
289stars

.claude-plugin/plugins/axiom/skills/axiom-uikit-animation-debugging/SKILL.md

Last Verified

January 16, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/CharlesWiltgen/Axiom/blob/main/.claude-plugin/plugins/axiom/skills/axiom-uikit-animation-debugging/SKILL.md -a claude-code --skill axiom-uikit-animation-debugging

Installation paths:

Claude
.claude/skills/axiom-uikit-animation-debugging/
Powered by add-skill CLI

Instructions

# UIKit Animation Debugging

## Overview

CAAnimation issues manifest as missing completion handlers, wrong timing, or jank under specific conditions. **Core principle** 90% of CAAnimation problems are CATransaction timing, layer state, or frame rate assumptions, not Core Animation bugs.

## Red Flags โ€” Suspect CAAnimation Issue

If you see ANY of these, suspect animation logic not device behavior:
- Completion handler fires on simulator but not device
- Animation duration (0.5s) doesn't match visual duration (1.2s)
- Spring animation looks correct on iPhone 15 Pro but janky on older devices
- Gesture + animation together causes stuttering (fine separately)
- `[weak self]` in completion handler and you're not sure why
- โŒ **FORBIDDEN** Hardcoding duration/values to "match what actually happens"
  - This ships device-specific bugs to users on different hardware
  - Do not rationalize this as a "temporary fix" or "good enough"

**Critical distinction** Simulator often hides timing issues (60Hz only, no throttling). Real devices expose them (variable frame rate, CPU throttling, background pressure). **MANDATORY: Test on real device (oldest supported model) before shipping.**

## Mandatory First Steps

**ALWAYS run these FIRST** (before changing code):

```swift
// 1. Check if completion is firing at all
animation.completion = { [weak self] finished in
    print("๐Ÿ”ฅ COMPLETION FIRED: finished=\(finished)")
    guard let self = self else {
        print("๐Ÿ”ฅ SELF WAS NIL")
        return
    }
    // original code
}

// 2. Check actual duration vs declared
let startTime = Date()
let anim = CABasicAnimation(keyPath: "position.x")
anim.duration = 0.5  // Declared
layer.add(anim, forKey: "test")

DispatchQueue.main.asyncAfter(deadline: .now() + 0.51) {
    print("Elapsed: \(Date().timeIntervalSince(startTime))")  // Actual
}

// 3. Check what animations are active
if let keys = layer.animationKeys() {
    print("Active animations: \(keys)")
    for key in keys {
        if l

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
15570 chars