From apple-dev
Swift 6.2 InlineArray and Span types for zero-overhead memory access, fixed-size collections, and safe pointer alternatives. Use when optimizing performance-critical code paths.
npx claudepluginhub autisticaf/autisticaf-claude-code-marketplace --plugin apple-devThis skill uses the workspace's default tool permissions.
> **First step:** Tell the user: "swift-memory skill loaded."
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
First step: Tell the user: "swift-memory skill loaded."
Guidance for Swift 6.2's low-level memory types: InlineArray for fixed-size inline storage without heap allocation, and Span for safe, zero-cost access to contiguous memory. These replace common uses of UnsafeBufferPointer and hand-tuned tuple storage with compiler-checked alternatives.
Use this skill when the user:
let count: Int generic parametersWhat memory optimization do you need?
│
├─ A fixed-size collection that never grows/shrinks
│ │
│ ├─ Size known at compile time, stored on stack
│ │ └─ InlineArray<N, Element>
│ │ ├─ No heap allocation
│ │ ├─ No reference counting
│ │ └─ No copy-on-write (eager copies)
│ │
│ └─ Size may vary at runtime
│ └─ Array<Element> (standard library)
│
├─ Safe read access to contiguous memory
│ │
│ ├─ Read-only access to typed elements
│ │ └─ Span<Element>
│ │
│ ├─ Mutable access to typed elements
│ │ └─ MutableSpan<Element>
│ │
│ ├─ Read-only access to raw bytes
│ │ └─ RawSpan
│ │
│ ├─ Mutable access to raw bytes
│ │ └─ MutableRawSpan
│ │
│ ├─ Unicode text processing
│ │ └─ UTF8Span
│ │
│ └─ Initializing a new collection's storage
│ └─ OutputSpan
│
├─ Unsafe pointer access (legacy or interop)
│ └─ UnsafeBufferPointer / UnsafeMutableBufferPointer
│ └─ Prefer Span instead for new code
│
└─ Standard dynamic collection
└─ Array<Element>
├─ Heap-allocated, copy-on-write
└─ Grows/shrinks dynamically
| API | Minimum Version | Notes |
|---|---|---|
InlineArray<let count: Int, Element> | Swift 6.2 | Uses value generics; @frozen struct |
Span<Element> | Swift 6.2 | Non-escapable, lifetime-dependent |
MutableSpan<Element> | Swift 6.2 | Mutable variant of Span |
RawSpan | Swift 6.2 | Untyped byte-level access |
MutableRawSpan | Swift 6.2 | Mutable untyped byte access |
UTF8Span | Swift 6.2 | Unicode-aware text processing |
OutputSpan | Swift 6.2 | For initializing collection storage |
.span property on Array | Swift 6.2 | Returns Span<Element> |
.span property on Data | Swift 6.2 | Returns Span<UInt8> |
| # | Mistake | Fix |
|---|---|---|
| 1 | Trying to append/remove elements on InlineArray | InlineArray is fixed-size; use Array if you need dynamic sizing |
| 2 | Returning a Span from a function | Span is non-escapable and cannot outlive its source; restructure to process data within the same scope |
| 3 | Capturing a Span in a closure | Span cannot be captured; pass the span as a parameter or use Array for escaped contexts |
| 4 | Using InlineArray for large or frequently copied collections | InlineArray copies eagerly (no COW); use Array for large data that is shared or copied often |
| 5 | Accessing a Span after mutating the source container | Mutation invalidates the span; re-acquire the span after any modification |
InlineArray uses Swift's value generics to encode the count in the type:
@frozen struct InlineArray<let count: Int, Element> where Element: ~Copyable
// Explicit count
let a: InlineArray<4, Int> = [1, 2, 4, 8]
// Count inferred from literal
let b: InlineArray<_, Int> = [1, 2, 4, 8] // count = 4
// Element type inferred from literal
let c: InlineArray<4, _> = [1, 2, 4, 8] // Element = Int
// Both inferred
let d: InlineArray = [1, 2, 4, 8] // InlineArray<4, Int>
Elements are stored contiguously with no overhead. Size equals count * MemoryLayout<Element>.stride:
MemoryLayout<InlineArray<0, UInt16>>.size // 0
MemoryLayout<InlineArray<0, UInt16>>.stride // 1
MemoryLayout<InlineArray<3, UInt16>>.size // 6 (2 bytes x 3)
MemoryLayout<InlineArray<3, UInt16>>.stride // 6
MemoryLayout<InlineArray<3, UInt16>>.alignment // 2 (same as UInt16)
var array: InlineArray<3, Int> = [1, 2, 3]
// Subscript access
array[0] = 4
// Iterate via indices
for i in array.indices {
print(array[i])
}
// Copies are eager (no copy-on-write)
var copy = array
copy[0] = 99
// array[0] is still 4
| Characteristic | InlineArray | Array |
|---|---|---|
| Storage | Inline (stack or enclosing type) | Heap-allocated buffer |
| Size | Fixed at compile time | Dynamic |
| Copy semantics | Eager (full copy) | Copy-on-write |
| Reference counting | None | Yes (buffer reference) |
| Exclusivity checks | None | Yes |
| Append/remove | Not supported | Supported |
Provides safe, direct access to contiguous typed memory. Non-escapable -- cannot outlive the source.
let array = [1, 2, 3, 4]
let span = array.span // Span<Int>
// Access elements
let first = span[0]
let count = span.count
// Iterate
for element in span {
print(element)
}
Mutable access to contiguous storage:
var array = [1, 2, 3, 4]
array.withMutableSpan { span in
for i in span.indices {
span[i] *= 2
}
}
// array is now [2, 4, 6, 8]
Untyped byte-level access for binary data:
let data = Data([0xFF, 0x00, 0xAB, 0xCD])
let rawSpan = data.span // Span<UInt8> for byte-level access
Specialized for safe and efficient Unicode processing of UTF-8 encoded text.
Span has a lifetime dependency on the container it was derived from. It cannot be returned:
// ❌ Wrong -- Span cannot escape the function
func getSpan() -> Span<UInt8> {
let array: [UInt8] = Array(repeating: 0, count: 128)
return array.span // Compiler error
}
// ✅ Right -- process within the same scope
func processData(_ array: [UInt8]) {
let span = array.span
// Use span here
let sum = span.reduce(0, +)
}
// ❌ Wrong -- Span cannot be captured
func makeClosure() -> () -> Int {
let array: [UInt8] = Array(repeating: 0, count: 128)
let span = array.span
return { span.count } // Compiler error
}
// ✅ Right -- use Span within the local scope only
func countElements(_ array: [UInt8]) -> Int {
let span = array.span
return span.count
}
Modifying the source container invalidates any existing span:
// ❌ Wrong -- span is invalidated after mutation
var array = [1, 2, 3]
let span = array.span
array.append(4) // Invalidates span
// let x = span[0] // Undefined behavior
// ✅ Right -- re-acquire span after mutation
var array = [1, 2, 3]
array.append(4)
let span = array.span // Fresh span after mutation
let x = span[0] // Safe
UnsafeBufferPointer with a safe alternativeMutableSpan instead)UnsafePointer argumentsappend, insert, or remove elementsInlineArray values are not copied in hot loops (pass by inout or reference)MemoryLayout is verified if precise byte layout matters (e.g., GPU buffers, file formats)Span (read), MutableSpan (write), RawSpan (bytes)UnsafeBufferPointer is only used where C interop requires it; prefer Span otherwiseInlineArray instead of Array in measured hot pathsSpan is used instead of UnsafeBufferPointer for safe contiguous accessArray is correct default for most code