Introduction: Why Documentation is an Investment in Your Swift Project's Future
Every iOS or macOS developer has at least once encountered a situation where someone else's (or their own) code turns into a "dark forest" after a month. Without quality documentation, project support becomes a nightmare, and onboarding new team members turns into weeks of torment. For the Swift language, with its powerful type system and protocols, documentation is especially important: it explains not only how the code works, but also why it was designed that way.
In this article, we will cover the complete cycle of writing documentation for a Swift project: from choosing tools to publishing. You will learn how to use the built-in capabilities of Xcode, the DocC format, and Markdown to make your documentation clear, relevant, and useful.
1. Basics: Formats and Tools for Swift Documentation
1.1. Markdown and DocC — The Industry Standard
Starting with Xcode 13, Apple has been actively promoting DocC (Documentation Compiler) — a system that combines code comments and Markdown articles into a single HTML document. DocC uses extended Markdown syntax, including support for symbol links, diagrams, and interactive examples.
A basic comment in Swift looks like this:
/// Calculates the factorial of a number./// - Parameter number: A non-negative integer./// - Returns: The factorial of the number (UInt64)./// - Warning: Overflow will occur if number > 20.func factorial(of number: UInt64) -> UInt64 { return (1...number).reduce(1, *)}1.2. Basic DocC Tags
DocC supports many tags for structuring documentation. Here are the most important ones:
/// - Parameter— description of a function parameter/// - Returns— description of the return value/// - Throws— description of errors the function can throw/// - Warning— important warning/// - Note— additional note/// - Precondition— preconditions for calling/// - Complexity— algorithm complexity estimate (O(n), O(log n), etc.)
Example with multiple tags:
/// Loads data from the network./// - Parameter url: URL for the request./// - Parameter timeout: Timeout in seconds (default 30)./// - Throws: `NetworkError.invalidURL` if the url is invalid./// - Throws: `NetworkError.timeout` if the timeout is exceeded./// - Returns: Data of type `Data`./// - Complexity: O(1) for creating the request.func fetchData(from url: URL, timeout: TimeInterval = 30) async throws -> Data { // implementation}2. Structuring Documentation: From Module to Method
2.1. Documenting Modules and Types
Every public type (class, struct, enum) should have a brief description. For modules and large libraries, use separate Markdown files in the .docc folder of your project.
/// Module for working with user settings.////// This module provides a type-safe interface/// for reading and writing settings in `UserDefaults`.public struct SettingsManager { // ...}2.2. Documenting Protocols and Extensions
Protocols are one of the key concepts of Swift. Document not only the protocol itself but also its requirements:
/// Protocol for objects that can be serialized to JSON.public protocol JSONSerializable { /// Converts the object to a dictionary for JSON. /// - Returns: A dictionary `[String: Any]`. func toDictionary() -> [String: Any]}
extension JSONSerializable { /// Converts the object to a JSON string. /// - Returns: A JSON string or nil on error. func toJSONString() -> String? { guard let data = try? JSONSerialization.data(withJSONObject: toDictionary()) el