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.
- Doc comments are written in Swift source files.
- DocC turns source documentation into readable pages and symbol references.
- Doc comments can describe behavior, parameters, return values, errors, and examples.
- DocC can combine code symbols with tutorial-style articles and rendered markdown.
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:
- a reusable library or package
- a framework used by other teams
- a public SDK or API
- an internal module with a large surface area
- tutorials and guides that need to reference real symbols
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
- Documenting public Swift Package APIs so other developers can use them correctly.
- Adding parameter and return-value descriptions to functions that have non-obvious behavior.
- Explaining the meaning of enum cases, especially for state machines and domain models.
- Documenting protocol requirements so conforming types understand the contract.
- Writing tutorial articles in DocC that link directly to real symbols in your codebase.
- Creating an internal reference site for a framework or module.
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
- Doc comments do not replace deeper conceptual articles. A single symbol comment cannot explain a whole API design.
- Documentation quality depends on the code surface you expose. Private helpers usually do not need detailed public docs.
- DocC is strongest when your project is organized as symbols plus supplemental markdown articles, not just comments alone.
- Generated docs may not feel complete if your package has few public declarations or if comments are sparse.
- Some formatting is supported, but doc comments are not a full publishing system for arbitrary rich content.
- API documentation is easiest to maintain when declarations and comments move together during refactoring.
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
- Doc comments are written with /// or /** ... */.
- DocC reads documented symbols and can combine them with markdown articles.
- Use comments to explain purpose, expectations, and edge cases, not just obvious syntax.
- Keep parameter descriptions synchronized with the function signature.
- Good docs are part of the API, not an afterthought.
11. Practice Exercise
Write documentation for a small Swift type and verify that it explains the API clearly.
- Create a struct named Book with properties for title, author, and pageCount.
- Add doc comments to the type and each property.
- Add an initializer comment that explains each parameter.
- Include a short note about what pageCount means.
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.