Swift DocC and Doc Comments: Write API Documentation That Scales

Swift DocC and doc comments let you write documentation next to your code and turn it into browsable API docs. This matters because well-documented code is easier to use, easier to maintain, and much easier to ship to other developers without constant explanation.

Quick answer: Doc comments are the source-level comments you write in Swift with /// or /** ... */. DocC is Apple’s documentation system that reads those comments, plus symbol data and markdown articles, to generate rich documentation pages.

Difficulty: Beginner

You'll understand this better if you know: basic Swift syntax, how functions and types are declared, and the difference between code comments and executable code.

1. What Is Swift DocC and Doc Comments?

In Swift, doc comments are special comments written directly above declarations such as functions, properties, structs, classes, and enums. DocC is the documentation framework that collects those comments and presents them as structured API documentation.

Think of doc comments as the raw documentation you author, and DocC as the system that organizes and publishes it.

2. Why Swift DocC and Doc Comments Matter

Documentation is part of the public surface area of your code. If another developer cannot quickly understand what a type does or how a function should be used, they will either misuse it or avoid it.

Doc comments help you document directly where the code lives, which keeps explanations close to the implementation and easier to keep current. DocC then makes that documentation discoverable, searchable, and easier to read in a structured format.

They are especially valuable when you are building:

3. Basic Syntax or Core Idea

The simplest doc comment uses three slashes. Place it immediately above the declaration you want to document.

Minimal function documentation

This example documents a function that adds two integers:

/// Returns the sum of two integers.
func add(_ lhs: Int, _ rhs: Int) -> Int {
    return lhs + rhs
}

The comment describes the function in one sentence. In DocC and Xcode, that text becomes part of the symbol’s documentation.

Doc comment with parameters and return value

For public APIs, you often want more structure. Swift supports standard section labels such as - Parameters and - Returns:

/// Repeats a string a specified number of times.
///
/// - Parameters:
///   - text: The string to repeat.
///   - count: The number of times to repeat the string.
/// - Returns: A new string containing the repeated text.
func repeat(text: String, count: Int) -> String {
    return Array(repeating: text, count: count).joined()
}

Doc comments are still comments, so they do not affect runtime behavior. Their value comes from the tools that read them.

4. Step-by-Step Examples

Example 1: Documenting a struct

Types are one of the best places to use doc comments because they define the main purpose of a feature.

/// A lightweight value type that represents a temperature in Celsius.
struct CelsiusTemperature {
    /// The temperature value.
    var value: Double
}

The type comment explains the broader meaning of the struct, while the property comment explains the individual stored value.

Example 2: Documenting an initializer

Initializers should explain what a caller must provide and what the type guarantees after initialization.

struct User {
    let name: String
    let isAdmin: Bool

    /// Creates a user with a name and role.
    ///
    /// - Parameters:
    ///   - name: The display name for the user.
    ///   - isAdmin: A value indicating whether the user has admin access.
    init(name: String, isAdmin: Bool) {
        self.name = name
        self.isAdmin = isAdmin
    }
}

This helps readers understand required arguments without opening the implementation.

Example 3: Documenting an enum case and behavior

Enums often benefit from a short type summary and notes on each case when the meaning is not obvious.

/// Describes the current loading state of a resource.
enum LoadState {
    /// The resource has not started loading yet.
    case idle

    /// The resource is currently loading.
    case loading

    /// The resource finished loading successfully.
    case loaded
}

Case comments are useful when the names alone do not fully explain the state transitions.

Example 4: Using Markdown inside doc comments

Doc comments can include lightweight formatting such as lists and emphasis. This is useful when you want the generated docs to stay readable.

/// Saves the profile.
///
/// This method:
/// - Validates the input.
/// - Writes the data to disk.
/// - Returns the saved profile.
func saveProfile() {

A short list can often communicate workflow better than a dense paragraph.

5. Practical Use Cases

6. Common Mistakes

Mistake 1: Writing normal comments instead of doc comments

Regular comments are useful for implementation notes, but they do not become official symbol documentation. If you want Xcode and DocC to show the text with the declaration, use the documentation comment syntax.

Problem: A single slash comment is treated as a normal code comment, so documentation tools ignore it.

// Returns the sum of two integers.
func add(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

Fix: Use the triple-slash form for doc comments.

/// Returns the sum of two integers.
func add(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

The corrected version is recognized by Swift documentation tools and surfaces as API documentation.

Mistake 2: Describing the obvious instead of the contract

Good documentation explains behavior, expectations, or side effects. It is less helpful to restate what the code already obviously says.

Problem: The comment says the function adds numbers, but the code already makes that clear. It does not explain whether negative numbers are allowed, what happens with overflow, or why the function exists.

/// Adds two numbers.
func add(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

Fix: Document constraints and expectations that are not obvious from the signature alone.

/// Returns the sum of two integers using standard integer addition.
///
/// - Important: This function uses normal integer arithmetic and can overflow if the
///   values exceed Int limits.
func add(lhs: Int, rhs: Int) -> Int {
    return lhs + rhs
}

The improved version helps callers use the API safely and correctly.

Mistake 3: Forgetting to keep comment parameter names aligned with the signature

When you rename a parameter in code but do not update the comment, the docs become confusing. In some cases, symbol documentation can also look inconsistent with the actual API.

Problem: The comment still refers to count, but the function parameter is now named times.

/// Repeats a string a number of times.
///
/// - Parameters:
///   - text: The text to repeat.
///   - count: How many times to repeat it.
func repeat(text: String, times: Int) -> String {
    return Array(repeating: text, count: times).joined()
}

Fix: Update the documentation so each parameter label matches the current API.

/// Repeats a string a number of times.
///
/// - Parameters:
///   - text: The text to repeat.
///   - times: How many times to repeat it.
func repeat(text: String, times: Int) -> String {
    return Array(repeating: text, count: times).joined()
}

The corrected version keeps source, comments, and generated docs consistent.

7. Best Practices

Practice 1: Start with a one-sentence summary

The first sentence should answer what the symbol does at a glance. This sentence is often the first thing readers see in generated docs.

/// Loads the saved profile from disk.
///
/// - Returns: The stored profile if one exists.
func loadProfile() -> Profile? {

This works well because the user gets the purpose before the details.

Practice 2: Document the non-obvious behavior

If a function validates, throws, mutates state, or has limits, say so directly.

/// Saves a document and overwrites the existing file if needed.
///
/// - Throws: An error if the file cannot be written.
func save(document: Document) throws {

Readers need this information to choose the API correctly.

Practice 3: Keep docs close to public declarations

Public-facing declarations are the best candidates for documentation because they form the contract other code relies on.

public struct Token {
    /// The raw token value.
    public let value: String
}

When docs sit directly above the declaration, they are less likely to drift out of date.

8. Limitations and Edge Cases

9. Practical Mini Project

Let’s build a tiny Swift module with documented API elements. The goal is to show how doc comments make the code self-explanatory and ready for DocC-style rendering.

/// A simple stopwatch that measures elapsed time in seconds.
struct Stopwatch {
    private var startTime: Date?

    /// Starts or restarts the stopwatch.
    mutating func start() {
        startTime = Date()
    }

    /// Returns the elapsed time since the stopwatch was started.
    ///
    /// - Returns: The number of seconds since start() was called, or nil if it has not started.
    func elapsed() -> TimeInterval? {
        guard let startTime = startTime else {
            return nil
        }

        return Date().timeIntervalSince(startTime)
    }
}

This small module shows the key idea behind DocC-friendly code: document the type, document the public behavior, and keep the explanations close to the API surface.

10. Key Points

11. Practice Exercise

Write documentation for a small Swift type and verify that it explains the API clearly.

Expected output: The source should read like a mini reference page, with a clear one-sentence summary and parameter descriptions that match the initializer.

Hint: Focus on behavior and meaning, not just restating the property names.

Solution:

/// Represents a book in a reading library.
struct Book {
    /// The book title shown to readers.
    let title: String

    /// The name of the author or authors.
    let author: String

    /// The total number of pages in the book.
    let pageCount: Int

    /// Creates a new book record.
    ///
    /// - Parameters:
    ///   - title: The title of the book.
    ///   - author: The author name.
    ///   - pageCount: The total number of pages. Use a value greater than zero.
    init(title: String, author: String, pageCount: Int) {
        self.title = title
        self.author = author
        self.pageCount = pageCount
    }
}

This exercise reinforces the main rule: documentation should help another developer use the API without reading the implementation first.

12. Final Summary

Swift doc comments are the source-level building blocks of API documentation. You write them directly above declarations, and tools such as Xcode and DocC can turn them into readable reference material.

DocC extends that idea by combining symbol documentation with richer articles, links, and structured content. Together, they help you create docs that are easier to navigate and more useful than scattered notes or external writeups.

If you want to improve a Swift module next, start by documenting the public types and functions that other developers touch first. Then expand from short summaries to parameter details, return values, and edge-case notes as your API grows.