Token导航 LogoToken导航

Agent Skill · 研究检索

axiom-uikit-animation-debugging(axiom uikit 动画调试)

用于辅助视频生成、动画合成、脚本化剪辑或 Remotion 等视频项目开发。它适合让 Agent 组织镜头、生成素材说明、维护合成代码或排查渲染问题。使用时需要确认分辨率、时长、素材路径和导出格式;涉及外部素材、人物肖像或商业发布时,应先核对版权授权和内容审核要求。

axiom-uikit-animation-debugging 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为只读;许可证为 MIT,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 21,305。

总安装 4,914周安装 192GitHub Stars 873下载 1,505核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:axiom-uikit-animation-debugging(axiom uikit 动画调试)
来源仓库:https://github.com/charleswiltgen/axiom
仓库路径:skills/axiom-uikit-animation-debugging
安装命令:
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-uikit-animation-debugging
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-uikit-animation-debugging

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

axiom-uikit-animation-debugging 针对 CAAnimation 常见问题提供可视化调试路径与修复方案。适用于 Completion Handler 不触发、弹簧动画卡顿或特定设备上的帧率下降现象排查。

强调 CATransaction 提交时机与 layer 状态一致性检查,避免隐式动画意外启动。建议使用 Xcode View Debugger 叠加显示图层边界,快速定位遮挡或尺寸异常问题。所有动画操作应在后台队列准备数据,主线程仅负责提交最终动画对象实例。

来源仓库内路径:skills/axiom-uikit-animation-debugging

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/charleswiltgen/axiom --skill axiom-uikit-anima…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它标注为只读,先用只读任务试一次,确认行为符合预期再扩大使用范围。

常见问题

6 条

axiom-uikit-animation-debugging 怎么安装?

在终端执行 npx skills add https://github.com/charleswiltgen/axiom --skill axiom-uikit-animation-debug…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

axiom-uikit-animation-debugging 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

axiom-uikit-animation-debugging 需要什么权限?

权限级别是只读。该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

axiom-uikit-animation-debugging 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

axiom-uikit-animation-debugging 用的人多吗?

公开数据是累计安装 4,914 次,近一周安装 192 次,下载 1,505 次,GitHub 873 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

axiom-uikit-animation-debugging 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
axiom-uikit-animation-debugging

axiom uikit 动画调试 · 本页

4,914873只读MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

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):

// 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 let anim = layer.animation(forKey: key) {
            print("\(key): duration=\(anim.duration), removed=\(anim.isRemovedOnCompletion)")
        }
    }
}

// 4. Check layer state
print("Layer speed: \(layer.speed)")  // != 1.0 means timing is scaled
print("Layer timeOffset: \(layer.timeOffset)")  // != 0 means animation is offset
What this tells you
  • Completion print appears → Handler fires, issue is in callback code
  • Completion print missing → Handler not firing, check CATransaction/layer state
  • Elapsed time == declared → Duration is correct, visual jank is from frames
  • Elapsed time!= declared → CATransaction wrapping is changing duration
  • layer.speed!= 1.0 → Something is slowing animation
  • Active animations list is long → Multiple animations competing
MANDATORY INTERPRETATION

Before changing ANY code, you must identify which ONE diagnostic is the root cause:

  1. If completion fires but elapsed time!= declared duration → Apply Pattern 2 (CATransaction)
  2. If completion doesn't fire AND isRemovedOnCompletion is true → Apply Pattern 3
  3. If completion fires but visual is janky → MUST profile with Instruments first

- You cannot guess "it's probably frames" - prove it with data - Profile > Core Animation instrument shows frame drops with certainty - If you skip Instruments, you're guessing

If diagnostics are contradictory or unclear
  • STOP. Do NOT proceed to patterns yet
  • Add more print statements to narrow the cause
  • Ask: "The diagnostics show X and Y but Z doesn't match. What am I missing?"
  • Profile with Instruments > Core Animation if unsure

Decision Tree

CAAnimation problem?
├─ Completion handler never fires?
│  ├─ On simulator only?
│  │  └─ Simulator timing is different (60Hz). Test on real device.
│  ├─ On real device only?
│  │  ├─ Check: isRemovedOnCompletion and fillMode
│  │  ├─ Check: CATransaction wrapping
│  │  └─ Check: app goes to background during animation
│  └─ On both simulator and device?
│     ├─ Check: completion handler is set BEFORE adding animation
│     └─ Check: [weak self] is actually captured (not nil before completion)
│
├─ Duration mismatch (declared != visual)?
│  ├─ Is layer.speed != 1.0?
│  │  └─ Something scaled animation duration. Find and fix.
│  ├─ Is animation wrapped in CATransaction?
│  │  └─ CATransaction.setAnimationDuration() overrides animation.duration
│  └─ Is visual duration LONGER than declared?
│     └─ Simulator (60Hz) vs device frame rate (120Hz). Recalculate for real hardware.
│
├─ Spring physics wrong on device?
│  ├─ Are values hardcoded for one device?
│  │  └─ Use device performance class, not model
│  ├─ Are damping/stiffness values swapped with mass/stiffness?
│  │  └─ Check CASpringAnimation parameter meanings
│  └─ Does it work on simulator but not device?
│     └─ Simulator uses 60Hz. Device may use 120Hz. Recalculate.
│
└─ Gesture + animation jank?
   ├─ Are animations competing (same keyPath)?
   │  └─ Remove old animation before adding new
   ├─ Is gesture updating layer while animation runs?
   │  └─ Use CADisplayLink for synchronized updates
   └─ Is gesture blocking the main thread?
      └─ Profile with Instruments > Core Animation

Common Patterns

Pattern Selection Rules (MANDATORY)

Apply ONE pattern at a time, in this order
  1. Always start with Pattern 1 (Completion Handler Basics)

- If completion NEVER fires → Pattern 1 - Verify completion is set BEFORE add() with print statement (line 33) - Only proceed to Pattern 2 if completion FIRES but timing is wrong

  1. Then Pattern 2 (CATransaction duration mismatch)

- Only if completion fires but elapsed time!= declared duration - Check logs from Mandatory First Steps (line 40-47)

  1. Then Pattern 3 (isRemovedOnCompletion)

- Only if animation completes but visual state reverts

  1. Patterns 4-7 Apply based on specific symptom (see Decision Tree line 91+)
FORBIDDEN
  • ❌ Applying multiple patterns at once ("let me try Pattern 2 AND Pattern 4 together")
  • ❌ Skipping Pattern 1 because "I already know it's not that"
  • ❌ Combining patterns without understanding why each is needed
  • ❌ Trying patterns randomly and hoping one works

Pattern 1: Completion Handler Basics

❌ WRONG (Handler set AFTER adding animation)
layer.add(animation, forKey: "myAnimation")
animation.completion = { finished in  // ❌ Too late!
    print("Done")
}
✅ CORRECT (Handler set BEFORE adding)
animation.completion = { [weak self] finished in
    print("🔥 Animation finished: \(finished)")
    guard let self = self else { return }
    self.doNextStep()
}
layer.add(animation, forKey: "myAnimation")

Why Completion handler must be set before animation is added to layer. Setting after does nothing.


Pattern 2: CATransaction vs animation.duration

❌ WRONG (CATransaction overrides animation duration)
CATransaction.begin()
CATransaction.setAnimationDuration(2.0)  // ❌ Overrides all animations!
let anim = CABasicAnimation(keyPath: "position")
anim.duration = 0.5  // This is ignored
layer.add(anim, forKey: nil)
CATransaction.commit()  // Animation takes 2.0 seconds, not 0.5
✅ CORRECT (Set duration on animation, not transaction)
let anim = CABasicAnimation(keyPath: "position")
anim.duration = 0.5
layer.add(anim, forKey: nil)
// No CATransaction wrapping

Why CATransaction.setAnimationDuration() affects ALL animations in the transaction block. Use it only if you want to change all animations uniformly.


Pattern 3: isRemovedOnCompletion & fillMode

❌ WRONG (Animation disappears after completion)
let anim = CABasicAnimation(keyPath: "opacity")
anim.fromValue = 1.0
anim.toValue = 0.0
anim.duration = 0.5
layer.add(anim, forKey: nil)
// After 0.5s, animation is removed AND layer reverts to original state
✅ CORRECT (Keep animation state)
anim.isRemovedOnCompletion = false
anim.fillMode = .forwards  // Keep final state after animation
layer.add(anim, forKey: nil)
// After 0.5s, animation state is preserved

Why By default, animations are removed and layer reverts. For permanent state changes, set isRemovedOnCompletion = false and fillMode =.forwards.


Pattern 4: Weak Self in Completion (MANDATORY)

❌ FORBIDDEN (Strong self creates retain cycle)
anim.completion = { finished in
    self.property = "value"  // ❌ GUARANTEED retain cycle
}
✅ MANDATORY (Always use weak self)
anim.completion = { [weak self] finished in
    guard let self = self else { return }
    self.property = "value"  // Safe to access
}
Why this is MANDATORY, not optional
  • CAAnimation keeps completion handler alive until animation completes
  • Completion handler captures self strongly (unless explicitly weak)
  • Creates retain cycle: self → animation → completion → self
  • Memory leak occurs even if animation is short-lived (0.3s doesn't prevent it)
FORBIDDEN rationalizations
  • ❌ "Animation is short, so no retain cycle risk"
  • ❌ "I'll remove the animation manually, so it's fine"
  • ❌ "This code path only runs once"
ALWAYS use [weak self] in completion handlers. No exceptions.

Pattern 5: Multiple Animations (Same keyPath)

❌ WRONG (Animations conflict)
// Add animation 1
let anim1 = CABasicAnimation(keyPath: "position.x")
anim1.toValue = 100
layer.add(anim1, forKey: "slide")

// Later, add animation 2
let anim2 = CABasicAnimation(keyPath: "position.x")
anim2.toValue = 200
layer.add(anim2, forKey: "slide")  // ❌ Same key, replaces anim1!
✅ CORRECT (Remove before adding)
layer.removeAnimation(forKey: "slide")  // Remove old first

let anim2 = CABasicAnimation(keyPath: "position.x")
anim2.toValue = 200
layer.add(anim2, forKey: "slide")

Or use unique keys:

let anim1 = CABasicAnimation(keyPath: "position.x")
layer.add(anim1, forKey: "slide_1")

let anim2 = CABasicAnimation(keyPath: "position.x")
layer.add(anim2, forKey: "slide_2")  // Different key

Why Adding animation with same key replaces previous animation. Either remove old animation or use unique keys.


Pattern 6: CADisplayLink for Gesture + Animation Sync

❌ WRONG (Gesture updates directly, animation updates at different rate)
func handlePan(_ gesture: UIPanGestureRecognizer) {
    let translation = gesture.translation(in: view)
    view.layer.position.x = translation.x  // ❌ Syncing issue
}

// Separately:
let anim = CABasicAnimation(keyPath: "position.x")
view.layer.add(anim, forKey: nil)  // Jank from desync
✅ CORRECT (Use CADisplayLink for synchronization)
var displayLink: CADisplayLink?

func startSyncedAnimation() {
    displayLink = CADisplayLink(
        target: self,
        selector: #selector(updateAnimation)
    )
    displayLink?.add(to: .main, forMode: .common)
}

@objc func updateAnimation() {
    // Update gesture AND animation in same frame
    let gesture = currentGesture
    let position = calculatePosition(from: gesture)
    layer.position = position  // Synchronized update
}

Why Gesture recognizer and CAAnimation may run at different frame rates. CADisplayLink syncs both to screen refresh rate.


Pattern 7: Spring Animation Device Differences

❌ WRONG (Hardcoded for one device)
let springAnim = CASpringAnimation()
springAnim.damping = 0.7  // Hardcoded for iPhone 15 Pro
springAnim.stiffness = 100
layer.add(springAnim, forKey: nil)  // Janky on iPhone 12
✅ CORRECT (Adapt to device performance)
let springAnim = CASpringAnimation()

// Use device performance class, not model
if ProcessInfo.processInfo.processorCount >= 6 {
    // Modern A-series (A14+)
    springAnim.damping = 0.7
    springAnim.stiffness = 100
} else {
    // Older A-series
    springAnim.damping = 0.85
    springAnim.stiffness = 80
}

layer.add(springAnim, forKey: nil)

Why Spring physics feel different at 60Hz vs 120Hz. Use device class (core count, GPU) not model.


Quick Reference Table

IssueCheckFix
Completion never firesSet handler BEFORE add()Move completion = before add()
Duration mismatchIs CATransaction wrapping?Remove CATransaction or remove animation from it
Jank on older devicesIs value hardcoded?Use ProcessInfo for device class
Animation disappearsisRemovedOnCompletion?Set to false, use fillMode =.forwards
Gesture + animation jankSynced updates?Use CADisplayLink
Multiple animations conflictSame key?Use unique keys or removeAnimation() first
Weak self in handlerCompletion captured correctly?Always use [weak self] in completion

When You're Stuck After 30 Minutes

If you've spent >30 minutes and the animation is still broken:

STOP. You either
  1. Skipped a mandatory step (most common)
  2. Misinterpreted diagnostic output
  3. Applied wrong pattern for your symptom
  4. Are in the 5% edge case requiring Instruments profiling
MANDATORY checklist before claiming "skill didn't work"
  • I ran ALL 4 diagnostic blocks from Mandatory First Steps (lines 28-63)
  • I pasted the EXACT output of diagnostics (logs, print statements)
  • I identified ONE root cause from "What this tells you" (lines 66-72)
  • I applied the FIRST matching pattern from Decision Tree (lines 91+)
  • I tested the pattern on a REAL device, not just simulator
  • I verified the pattern with print statements/logs showing the fix worked
If ALL boxes are checked and still broken
  • You MUST profile with Instruments > Core Animation
  • Time cost: 30-60 minutes (unavoidable for edge cases)
  • Hardcoding, asyncAfter, or "shipping and hoping" are FORBIDDEN
  • Ask for guidance before adding any workarounds
Time cost transparency
  • Pattern 1: 2-5 minutes
  • Pattern 2: 3-5 minutes
  • Instruments profiling: 30-60 minutes (for edge cases only)
  • Trying random fixes without profiling: 2-4 hours + risk of shipping broken

Common Mistakes

❌ Setting completion handler AFTER adding animation

  • Completion is not set in time
  • Fix: Set completion BEFORE layer.add()

❌ Assuming simulator timing = device timing

  • Simulator runs 60Hz, devices run 60Hz-120Hz
  • Fix: Test on real device before tuning duration

❌ Hardcoding device-specific values

  • "This value works on iPhone 15 Pro" → fails on iPhone 12
  • Fix: Use ProcessInfo.processInfo.processorCount or test class

❌ Wrapping animation in CATransaction.setAnimationDuration()

  • Overrides all animation durations in that transaction
  • Fix: Set duration on animation, not transaction

❌ FORBIDDEN: Using strong self in completion handler

  • GUARANTEED retain cycle: self → animation → completion → self
  • Fix: ALWAYS use [weak self] with guard

❌ Not removing old animation before adding new

  • Same keyPath replaces previous animation
  • Fix: layer.removeAnimation(forKey:) first or use unique keys

❌ Ignoring layer.speed and layer.timeOffset

  • These scale animation timing invisibly
  • Fix: Check these values if timing is wrong

Real-World Impact

Before CAAnimation debugging 2-4 hours per issue

  • Print everywhere, test on simulator, hardcode values, ship and hope
  • "Maybe it's a device bug?"
  • DispatchQueue.asyncAfter as fallback timer

After 15-30 minutes with systematic diagnosis

  • Check completion handler setup (2 min)
  • Check CATransaction wrapping (3 min)
  • Check layer state and duration mismatch (5 min)
  • Identify root cause, apply pattern (5 min)
  • Test on real device (varies)

Key insight CAAnimation issues are almost always CATransaction, layer state, or frame rate assumptions, never Core Animation bugs.


Last Updated: 2025-11-30 Status: TDD-tested with pressure scenarios Framework: UIKit CAAnimation

平台分布

Claude Code

28.01%
按下载量换算422

Codex

24.43%
按下载量换算368

OpenCode

17.86%
按下载量换算269

Antigravity

12.39%
按下载量换算186

Cursor

8.58%
按下载量换算129

Gemini CLI

3.75%
按下载量换算56

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills