Skip to content
✓ValidatedNov 2025 · 3 pressure scenarios passed What's this?

UIKit Animation Debugging ​

Systematic CAAnimation diagnosis covering completion handlers, spring physics, timing mismatches, and gesture conflicts. CAAnimation behavior differs significantly between simulator and device.

When to Use ​

Use this skill when:

  • CAAnimation completion handler never fires
  • Spring animation looks wrong on real device (but fine in simulator)
  • Animation duration doesn't match specified value
  • Animation stutters during pan gesture
  • Multiple animations interfere with each other

Example Prompts ​

  • "My CAAnimation completion handler never fires"
  • "Spring animation looks perfect in simulator but bounces wrong on iPhone"
  • "Animation duration is 0.3 but actually takes 0.5 seconds"
  • "When I pan a gesture and trigger animation, it's janky"

What This Skill Provides ​

Pattern 1: Completion Handler That Never Fires ​

CABasicAnimation has no completion property — use CATransaction:

swift
CATransaction.begin()
CATransaction.setCompletionBlock {
    print("Animation finished")  // This fires reliably
}
let animation = CABasicAnimation(keyPath: "position")
// ... configure animation
view.layer.add(animation, forKey: "move")
CATransaction.commit()

Pattern 2: Spring Physics Device Differences ​

Simulator runs at 60 FPS, iPhone Pro at 120 FPS (ProMotion). Spring physics need 1.5-2x higher damping/stiffness for ProMotion:

swift
// Tuned for ProMotion
spring.damping = 15    // Not 10
spring.stiffness = 150 // Not 100

Pattern 3: Duration Mismatch ​

Don't mix UIView.animate and CAAnimation durations:

swift
CATransaction.begin()
CATransaction.setAnimationDuration(0.3)  // Single source of truth
// ... add animations
CATransaction.commit()

Pattern 4: Gesture + Animation Jank ​

Use CADisplayLink with .common mode for gesture-driven animation:

swift
displayLink.add(to: .main, forMode: .common)  // Runs during gesture

Debugging Tools ​

swift
view.layer.animationKeys()           // List active animations
view.layer.presentation()?.position  // Get animated value (not final)
view.layer.speed = 0.1               // Slow down 10x for debugging

Resources ​

Docs: /quartzcore

Released under the MIT License