Skip to content
Mobile
Skill

/swift

Design, implement, and review Swift APIs and Apple-platform code. Use when working on .swift files, Swift types, Foundation or AVFoundation APIs, DispatchQueue, async/await, Task, actors, MainActor, thread-affine state, or Swift-backed React Native Nitro Module implementations.

BOOST
From plugin
react-native-skills
1789 skills
Install
$ npx -y skills add margelo/react-native-skills --skill swift --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/swift

Context preview

The summary Claude sees to decide when to auto-load this skill.

Design, implement, and review Swift APIs and Apple-platform code. Use when working on .swift files, Swift types, Foundation or AVFoundation APIs, DispatchQueue, async/await, Task, actors, MainActor, thread-affine state, or Swift-backed React Native Nitro Module implementations.

SKILL.md

swift.SKILL.md
name: swift
description: Design, implement, and review Swift APIs and Apple-platform code. Use when working on .swift files, Swift types, Foundation or AVFoundation APIs, DispatchQueue, async/await, Task, actors, MainActor, thread-affine state, or Swift-backed React Native Nitro Module implementations.

Swift

Use this skill for Swift code that needs strong API boundaries, predictable threading, and idiomatic Apple-platform integration. When the code is part of a Nitro Module, pair this with `build-nitro-modules` for generated specs, Promise mapping, and HybridObject constraints.

Workflow

1. Read the local Swift code, generated protocols, and surrounding API shape before editing. 2. Choose the public type model first: make invalid states unrepresentable where Swift can express them. 3. Choose one concurrency model for the feature before writing implementation code. 4. Keep synchronous properties and methods cheap, local, and nonblocking. 5. Make queue hops, hardware/session negotiation, I/O, and fallible async work explicit in the API.

Type-Safe API Design

  • Represent state variants with types, not nullable clusters. Use protocols plus conforming structs/classes when variants share a public contract, or use `enum` with associated values when the set is closed and value-like.
  • Keep related fields nonoptional on the same variant. If `barcode` and `barcodeType` are meaningful only together, put both on `ScannedBarcode`; do not make both optional on a generic scanned-data struct.
  • Use optionals only for real domain absence inside one state, not for expressing which state the object is in.
  • Prefer compile-time flow over caller-side probing. If callers need repeated `if let` chains to discover valid field combinations, the API shape is probably wrong.
// Avoid: the valid combinations are implicit and easy to misuse.
struct ScannedData {
  let position: Point
  let text: String?
  let barcode: String?
  let barcodeType: BarcodeType?
  let face: Rect?
}

// Prefer: each state exposes the fields that are valid for that state.
protocol ScannedData {
  var position: Point { get }
}

struct ScannedText: ScannedData {
  let position: Point
  let text: String
}

struct ScannedBarcode: ScannedData {
  let position: Point
  let barcode: String
  let barcodeType: BarcodeType
}

struct ScannedFace: ScannedData {
  let position: Point
  let face: Rect
}

Concurrency Model

  • Choose Swift concurrency or DispatchQueue for a feature, not both as interleaved control flow.
  • Keep quick, deterministic, local work synchronous. Do not introduce `Task`, `DispatchQueue`, or Promise plumbing for simple value construction, cached metadata, or pure transforms.
  • Use Swift `async`/`await`, `Task`, and actors only when the full operation can be represented cleanly in Swift concurrency without queue escape hatches.
  • Use a private owned serial `DispatchQueue` when Apple APIs, delegates, callbacks, C++ bridges, JS runtimes, or Nitro thread boundaries already revolve around queues, or when heavier native work must not block the caller.
  • Avoid `DispatchQueue.main` unless the platform API requires the main thread, such as UIKit/AppKit/VisionKit presentation or view mutation. Keep main-thread blocks small and move parsing, conversion, I/O, session negotiation, and CPU work to an owned queue or async API.
  • Treat repeated `Task`, `DispatchQueue`, actor, or thread hops as an architecture smell. A component should either own the queue/actor it works on, or cross into that owner once at the public async boundary or native callback boundary.
  • If a workflow bounces between main, background, JS, and native queues in multiple nested places, stop and redesign the object/lifecycle/API. Excessive hops hide latency, make ordering harder to reason about, and create future performance problems.
  • Do not fix races or readiness bugs with `DispatchQueue.asyncAfter`, `Task.sleep`, `Thread.sleep`, timers, extra queue hops, or calling the same method twice. Fix the owner queue, lifecycle state, completion callback, delegate event, or async API boundary instead. Retry only for external nondeterminism such as hardware, OS services, remote services, or network, and keep retries bounded, cancellable, and idempotent.
  • Do not use `Task { @MainActor in ... }` as a generic main-thread hop from a nonisolated or Nitro-generated entry point. It creates unstructured Swift concurrency. Use it only when the operation is otherwise Swift-concurrency based and benefits from `async`/`await`, task cancellation, or actor isolation end to end.
  • For UIKit, AppKit, VisionKit, and other main-thread callback/delegate APIs, prefer a direct `DispatchQueue.main.async` boundary or an async public method that owns the hop. Direct `DispatchQueue.main.async` is understood by Swift's actor checker for `@MainActor` calls; generic queue wrappers such as `Promise.parallel(.main)` usually are not.
  • If a callback can return on an arbitrary queue, normalize it to the chosen owner queue once, close to the callback source, instead of scattering nested `Task { @MainActor }` or `DispatchQueue.main.async` hops through the workflow.
  • Do not force `MainActor.assumeIsolated`, `Thread.isMainThread` branches, or queue `.sync` calls to make a Swift-concurrency design compile. That is a signal to choose a queue-based design or change the API boundary.
  • Do not call `DispatchQueue.sync`, `DispatchQueue.main.sync`, or equivalent synchronous queue hops. Treat them as bugs, especially in property getters and setters.
  • Use `DispatchQueue.async` or a Nitro `Promise` method for queue-bound work that callers must wait for.
  • Treat locks as a last-resort synchronization primitive, not a default safety wrapper. Before adding `NSLock`, identify the concrete shared mutable values, the threads/queues that can access them concurrently, and why ownership by `MainActor`, a serial queue, a Nitro runtime/thread, or immutable snapshots is not enough.
  • Swift `Array` an
Read more
Ships withreact-native-skills

The best react-native Agent Skills. Forget 10x, this is 100x.

Get the whole plugin

Other skills on react-native-skills.