swift-api-design-guidelines
This skill applies Swift's official API design guidelines to help developers name types, methods, properties, parameters, and argument labels correctly. Use it when designing new Swift APIs, reviewing existing code for naming consistency, writing documentation comments, or refactoring for improved call site clarity and readability.
git clone --depth 1 https://github.com/dpearson2699/swift-ios-skills /tmp/swift-api-design-guidelines && cp -r /tmp/swift-api-design-guidelines/skills/swift-api-design-guidelines ~/.claude/skills/swift-api-design-guidelinesSKILL.md
# Swift API Design Guidelines
Apply the Swift API Design Guidelines to naming, labels, documentation, and
call-site clarity. For mixed requests, handle the API-design portion here and
route language/type-system work to `swift-language`, concurrency to
`swift-concurrency`, and lint configuration to `swiftlint`.
## Contents
- [Argument Label Rules](#argument-label-rules)
- [Side-Effect Naming](#side-effect-naming)
- [Mutating and Nonmutating Pairs](#mutating-and-nonmutating-pairs)
- [Documentation Comments](#documentation-comments)
- [Clarity and Naming](#clarity-and-naming)
- [Fluent Usage and Protocols](#fluent-usage-and-protocols)
- [General Conventions](#general-conventions)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## Argument Label Rules
Argument labels determine how a call site reads. Apply the first matching row:
| Situation | Rule | Example |
|-----------|------|---------|
| First arg completes grammatical phrase | Omit label, merge words into base name | `addSubview(y)` |
| Value-preserving init conversion | Omit first label | `Int64(someUInt32)` |
| Arguments are indistinguishable peers | Omit all labels | `min(x, y)` |
| First arg completes prepositional phrase | Label with preposition | `fade(from: red)` |
| First two args form a single abstraction | Fold preposition into base name | `moveTo(x: b, y: c)` |
| Everything else | Label it | `split(maxSplits: 2)` |
Load [Argument Labels and Parameters](references/argument-labels-and-parameters.md)
when resolving abstraction boundaries, multiple prepositions, conversion
initializers, indistinguishable peers, parameter naming, or default arguments.
## Side-Effect Naming
Use imperative verbs for operations with side effects, result-describing noun
or adjective phrases for operations without side effects, and assertion-style
names for Boolean APIs.
```swift
array.sort()
array.append(newElement)
let d = point.distance(to: origin)
line.isEmpty
set.contains(element)
```
Load [Side Effects and Mutating Pairs](references/side-effects-and-mutating-pairs.md)
when reviewing extended pure/mutating examples or Boolean naming.
## Mutating and Nonmutating Pairs
Name mutating/nonmutating pairs from the operation's natural description:
- For verb operations, use the imperative for mutation and a result-describing
participle for the copy: `sort()/sorted()` or `append(_:)/appending(_:)`.
Prefer `-ed`; use `-ing` only when `-ed` is ungrammatical or describes the
direct object instead of the returned result.
- For noun operations, use the noun for the copy and `form` + noun for
mutation: `union(_:)` / `formUnion(_:)`.
- Prefix factories that create new values with `make`.
Load the [`-ed`/`-ing` Decision Tree](references/side-effects-and-mutating-pairs.md#the--ed-ing-decision-tree)
when the returned-result grammar is unclear. The same reference contains
expanded `form`-prefix, Boolean, and factory patterns.
## Documentation Comments
Every public declaration must have a documentation comment.
### Summary rules by declaration kind
| Declaration | Summary describes |
|-------------|-------------------|
| Function / method | What it does and what it returns |
| Subscript | What it accesses |
| Initializer | What it creates |
| Type / property / variable | What it **is** |
Write summaries as a single sentence fragment, beginning with a verb (for actions) or a noun phrase (for entities), ending in a period.
```swift
/// Returns the element at the specified index.
func element(at index: Int) -> Element { ... }
/// The number of elements in the collection.
var count: Int { ... }
/// Creates a new array with the given elements.
init(_ elements: some Sequence<Element>) { ... }
/// Accesses the element at the specified position.
subscript(index: Int) -> Element { ... }
```
### Symbol markup
Use standard symbol markup after the summary when relevant:
- `- Parameter name:` for individual parameters
- `- Parameters:` block for multiple parameters
- `- Returns:` for the return value
- `- Throws:` for errors thrown
- `- Complexity:` for algorithmic complexity
```swift
/// Removes and returns the element at the specified position.
///
/// - Parameter index: The position of the element to remove.
/// - Returns: The removed element.
/// - Complexity: O(*n*), where *n* is the length of the collection.
mutating func remove(at index: Int) -> Element { ... }
```
### O(1) complexity rule
Document the complexity of any computed property that is not O(1). Callers assume properties are O(1) by default. If a property does more than constant-time work, state the complexity explicitly.
```swift
/// The total weight of all items.
///
/// - Complexity: O(*n*), where *n* is the number of items.
var totalWeight: Double {
items.reduce(0) { $0 + $1.weight }
}
```
For documentation patterns and examples, see [references/conventions-and-special-rules.md](references/conventions-and-special-rules.md).
## Clarity and Naming
Clarity at the point of use is the most important goal. Every design decision serves the person reading a call site.
**Clarity over brevity.** Longer names are acceptable when they remove ambiguity. Do not abbreviate.
```swift
// GOOD
employees.remove(at: position)
// BAD — ambiguous: remove the element? remove at position?
employees.remove(position)
```
**Include words needed to avoid ambiguity.** If omitting a word makes the call site unclear, keep it.
```swift
// GOOD — "at" clarifies the argument's role
friends.remove(at: index)
// BAD — is "index" the element to remove or the position?
friends.remove(index)
```
**Omit needless words.** Do not repeat type information already available from the context.
```swift
// GOOD
allViews.remove(cancelButton)
// BAD — "Element" repeats the type
allViews.removeElement(cancelButton)
```
**Name variables and parameters by role, not type.** Use the entity's role in the current context, not its type name.
```swift
//Discover and configure Bluetooth and Wi-Fi accessories using AccessorySetupKit. Use when presenting a privacy-preserving accessory picker, defining discovery descriptors for BLE or Wi-Fi devices, handling accessory session events, migrating from CoreBluetooth permission-based scanning, or setting up accessories without requiring broad Bluetooth permissions.
Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets.
Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement.
Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, system Stop and AlarmButton secondary actions, authorization, state observation, countdown widget-extension handoff, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.
Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store Connect experiences, size/capability constraints, NSUserActivity routing, SKOverlay promotion, App Group/keychain handoff, ephemeral notifications, location confirmation, and full-app migration. Use when creating App Clips or wiring App Clip invocation, experience configuration, or full-app handoff.
Implement App Intents for Siri, Shortcuts, Spotlight, widgets, Control Center, and Apple Intelligence on iOS. Covers AppIntent actions, AppEntity and EntityQuery models, AppShortcutsProvider phrases, IndexedEntity Spotlight indexing, WidgetConfigurationIntent, SnippetIntent, and assistant schemas. Use when exposing app actions or entities to system surfaces.
Optimize App Store product pages for search visibility and conversion. Use for App Store Optimization (ASO), keyword research, app name/subtitle/keyword-field strategy, conversion-focused descriptions and promotional text, screenshot captions and ordering, Custom Product Pages with assigned search keywords, In-App Events, Product Page Optimization tests, localized metadata, ratings/review strategy, and in-app review prompt timing with RequestReviewAction or AppStore.requestReview. Also use when routing ASO vs App Store review, privacy/ATT, or StoreKit implementation boundaries.
Audits App Store submission readiness and rejection risk across current review guidelines, PrivacyInfo.xcprivacy and required-reason APIs, privacy labels, ATT, StoreKit payments, metadata, entitlements, widgets, and Live Activities. Use when preparing a submission, responding to rejection, reconciling privacy evidence, or separating upload blockers from cleanup.