home / skills / hoangnguyen0403 / agent-skills-standard / memory-management

memory-management skill

/skills/swift/memory-management

This skill helps you apply Swift memory management best practices, reinforcing ARC fundamentals, capture lists, and avoiding retain cycles across code.

npx playbooks add skill hoangnguyen0403/agent-skills-standard --skill memory-management

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
1.3 KB
---
name: Swift Memory Management
description: Standards for ARC, Weak/Unowned References, and Capture Lists
metadata:
  labels: [swift, memory, arc, weak, unowned]
  triggers:
    files: ['**/*.swift']
    keywords: ['weak', 'unowned', 'capture', 'deinit', 'retain']
---

# Swift Memory Management

## **Priority: P0**

## Implementation Guidelines

### ARC Fundamentals

- **Default**: Strong references. Swift automatically manages retain/release.
- **Weak**: Use `weak` for delegate patterns and parent-child relationships.
- **Unowned**: Use `unowned` only when reference guaranteed to outlive (rare).

### Capture Lists

- **Closures**: Always use `[weak self]` or `[unowned self]` in escaping closures.
- **Self in Structs**: No capture list needed (`self` is copied by value).
- **Multiple Captures**: `[weak self, weak delegate]`.

### Retain Cycles

- **Delegates**: Always `weak var delegate`.
- **Closures as Properties**: Use `weak` or `unowned` in capture list.
- **two-way References**: One side must be `weak`.

## Anti-Patterns

- **Strong Delegates**: `**No strong var delegate**: Use weak.`
- **Missing Capture List**: `**No self in escaping closures**: Use [weak self].`
- **Unowned Misuse**: `**Avoid unowned**: Use weak unless certain.`

## References

- [Capture Lists & Retain Cycles](references/implementation.md)

Overview

This skill codifies Swift memory management standards focused on ARC, weak/unowned references, and closure capture lists. It provides clear guidelines to avoid retain cycles and common anti-patterns for delegates, closures, and two-way relationships. The goal is safer, predictable memory usage in Swift codebases.

How this skill works

The skill inspects code patterns and recommends appropriate reference qualifiers (strong, weak, unowned) and capture lists for closures. It flags delegate properties, closure properties, and bidirectional references, suggesting weak or unowned usage where appropriate. It also highlights risky anti-patterns like strong delegates, missing capture lists in escaping closures, and improper unowned use.

When to use it

  • When defining delegate properties to ensure no retain cycle between owner and delegate.
  • When assigning closures to properties or passing escaping closures to async APIs.
  • When modeling parent-child relationships where the parent should retain the child.
  • When two objects reference each other and one must be non-owning.
  • During code reviews to enforce consistent memory management conventions.

Best practices

  • Default to strong references; opt-in to weak for non-owning links like delegates.
  • Declare delegate properties as `weak var delegate` to prevent retain cycles.
  • Use `[weak self]` in escaping closures; use `[unowned self]` only if object lifetime is guaranteed.
  • Avoid storing closures as strong properties without weak captures; prefer capture lists for closure properties.
  • For structs, no capture list is required since self is value-copied.
  • When both sides reference each other, make exactly one side weak to break the cycle.

Example use cases

  • View controller and delegate: make the delegate weak to avoid retaining the view controller.
  • Asynchronous network callback capturing self: use `[weak self]` to prevent retaining controllers during network calls.
  • Closure stored as a property on an object: include a weak capture of self to avoid object never being released.
  • Parent-child model where parent owns child: child holds a weak reference back to parent.
  • Two-way model relationship: convert one relationship to weak to ensure proper deallocation.

FAQ

When should I use unowned instead of weak?

Use unowned only when you can guarantee the referenced object outlives the reference; otherwise prefer weak to avoid crashes from dangling pointers.

Do I need capture lists for non-escaping closures?

No. Non-escaping closures don’t create long-lived captures, so capture lists are unnecessary for value types and short-lived closures.