Swift Documentation
Good documentation is an essential part of writing maintainable and collaborative code. In this guide, we'll explore Swift's documentation capabilities, from basic comments to rich formatted documentation that works with Xcode and other tools.
Why Document Your Code?
Documentation serves multiple purposes:
- Helps others understand your code's purpose and usage
- Makes your code more maintainable, even for your future self
- Provides hints and guidance in code editors
- Can be extracted to generate external documentation
Basic Comments in Swift
Let's start with the simplest form of documentation - comments. Swift supports two types of comments:
Single-line Comments
Single-line comments start with //
:
// This is a single-line comment
let name = "Swift Developer" // This is an inline comment
Multi-line Comments
Multi-line comments start with /*
and end with */
:
/* This is a
multi-line
comment */
let complexCalculation = 42 /* We can also use
multi-line comments
inline */
Swift Documentation Comments
Swift supports rich documentation comments that can be processed by Xcode and other tools. These special comments use three slashes ///
or a multi-line comment with an extra asterisk /**
.
Basic Documentation Comment
/// A simple function that greets a person
func greet(person: String) -> String {
return "Hello, \(person)!"
}
Multi-line Documentation Comment
/**
A more complex function that greets a person
with customization options.
*/
func greet(person: String, formally: Bool = false) -> String {
if formally {
return "Good day, \(person)."
} else {
return "Hello, \(person)!"
}
}
Documentation Markup
Swift's documentation system supports a rich markup syntax that lets you format your documentation. This markup is similar to Markdown.
Paragraphs and Formatting
/**
This is a paragraph of text.
This is another paragraph with **bold** and *italic* text.
You can also use `code` formatting for inline code.
# Heading Level 1
## Heading Level 2
### Heading Level 3
*/
class FormattedDocumentation {
// Class implementation
}
Lists
/**
You can create lists:
- First item
- Second item
- Third item
Or numbered lists:
1. First step
2. Second step
3. Third step
*/
struct DocumentedStruct {
// Struct implementation
}
Code Blocks
/**
Here's an example of how to use this function:
let greeting = greet(person: "John") print(greeting) // Output: Hello, John!
*/
func greet(person: String) -> String {
return "Hello, \(person)!"
}
Special Documentation Keywords
Swift's documentation system supports special keywords that highlight important aspects of your code.
Parameter Documentation
/**
Calculates the distance between two points.
- Parameters:
- x1: The x-coordinate of the first point
- y1: The y-coordinate of the first point
- x2: The x-coordinate of the second point
- y2: The y-coordinate of the second point
- Returns: The distance between the two points
*/
func distance(x1: Double, y1: Double, x2: Double, y2: Double) -> Double {
let dx = x2 - x1
let dy = y2 - y1
return sqrt(dx*dx + dy*dy)
}
For functions with fewer parameters, you can use individual parameter tags:
/**
Greets a person with an optional custom message.
- Parameter name: The name of the person to greet
- Parameter message: An optional custom message to include
- Returns: A greeting string
*/
func greet(name: String, message: String? = nil) -> String {
if let message = message {
return "Hello, \(name)! \(message)"
} else {
return "Hello, \(name)!"
}
}
Other Common Keywords
/**
Uploads a file to a remote server.
- Parameters:
- file: The file to upload
- server: The server URL
- Returns: A unique identifier for the uploaded file
- Throws: `NetworkError.connectionFailed` if the network is unavailable
- Throws: `FileError.accessDenied` if the file cannot be read
- Warning: This method requires an internet connection
- Note: Large files may take some time to upload
- Important: The server must support the XYZ protocol
- SeeAlso: `downloadFile(id:to:)`
*/
func uploadFile(file: URL, to server: URL) throws -> String {
// Implementation
return "file-123"
}
Documenting Different Swift Elements
Classes and Structs
/// A class representing a book in a library
class Book {
/// The title of the book
let title: String
/// The author of the book
let author: String
/// The year the book was published
let yearPublished: Int
/**
Creates a new book with the specified details.
- Parameters:
- title: The title of the book
- author: The author of the book
- yearPublished: The year the book was published
*/
init(title: String, author: String, yearPublished: Int) {
self.title = title
self.author = author
self.yearPublished = yearPublished
}
}
Enumerations
/**
Represents the seasons of the year.
Each case corresponds to one of the four astronomical seasons
in the northern hemisphere.
*/
enum Season {
/// Winter season, characterized by cold weather and possible snow
case winter
/// Spring season, characterized by warming temperatures and blooming plants
case spring
/// Summer season, characterized by hot weather and longer days
case summer
/// Fall/Autumn season, characterized by cooling temperatures and falling leaves
case fall
}
Protocols
/**
A protocol that describes an entity that can process payments.
Conforming types should implement methods to process different
types of payment methods safely and reliably.
*/
protocol PaymentProcessor {
/**
Process a credit card payment.
- Parameters:
- cardNumber: The credit card number
- expiryDate: The expiry date in MM/YY format
- amount: The amount to charge
- Returns: A transaction ID for the payment
- Throws: `PaymentError` if the payment fails
*/
func processCreditCardPayment(cardNumber: String,
expiryDate: String,
amount: Decimal) throws -> String
/**
Process a digital wallet payment.
- Parameters:
- walletId: The wallet identifier
- amount: The amount to charge
- Returns: A transaction ID for the payment
- Throws: `PaymentError` if the payment fails
*/
func processWalletPayment(walletId: String,
amount: Decimal) throws -> String
}
Real-World Example: Documented App Feature
Here's a more comprehensive example showing how good documentation practices can be applied to a real-world app feature:
/**
WeatherService provides functionality to fetch weather data
from remote APIs and parse it into application models.
## Usage
let service = WeatherService(apiKey: "your-api-key")
// Fetch current weather
service.fetchCurrentWeather(forCity: "New York") { result in
switch result {
case .success(let weather):
print("Temperature: \(weather.temperature)°C")
case .failure(let error):
print("Failed to fetch weather: \(error)")
}
}
- Important: You need to obtain an API key from the weather provider
- Note: This service caches responses for 10 minutes to reduce API usage
*/
class WeatherService {
/// Error types that can occur when fetching weather data
enum WeatherError: Error {
/// The API key is invalid or expired
case invalidApiKey
/// The requested location was not found
case locationNotFound
/// The network request failed
case networkFailure(Error)
/// The response data couldn't be parsed correctly
case invalidData
}
/// The API key used for authentication
private let apiKey: String
/// The cache for storing recent weather data
private var cache: [String: (weather: Weather, timestamp: Date)] = [:]
/**
Creates a new weather service.
- Parameter apiKey: The API key for authentication
*/
init(apiKey: String) {
self.apiKey = apiKey
}
/**
Fetches the current weather for the specified city.
- Parameters:
- city: The name of the city
- completion: A closure that will be called with the result
- Note: Results are cached for 10 minutes to reduce API calls
*/
func fetchCurrentWeather(forCity city: String,
completion: @escaping (Result<Weather, WeatherError>) -> Void) {
// Implementation details
// ...
}
}
Viewing Documentation in Xcode
Once you've written documentation comments, Xcode will display them in several ways:
- Quick Help: Option-click on a symbol to see its documentation
- Documentation Inspector: View the Developer Documentation window (Help > Developer Documentation)
- Code Completion: See brief documentation as you type
Documentation Generation Tools
You can also use tools to generate standalone documentation websites from your Swift code comments:
- Swift-DocC - Apple's official documentation compiler
- Jazzy - A command-line utility that generates documentation for Swift and Objective-C
- SourceDocs - Generates Markdown documentation from Swift code
Best Practices for Swift Documentation
- Document public interfaces: At minimum, document all public APIs that other developers will use
- Be concise but complete: Cover what's needed without unnecessary details
- Use examples: Real code examples help users understand how to use your code
- Keep documentation updated: Update documentation when code changes
- Use proper formatting: Take advantage of markup for readability
- Document edge cases and errors: Explain what happens when things go wrong
- Document assumptions: Note any assumptions your code makes
Summary
Good documentation is a key component of writing maintainable Swift code. Swift's rich documentation system allows you to create clear, formatted documentation that integrates with Xcode and other tools. By following the practices outlined in this guide, you can make your code more accessible, maintainable, and professional.
Additional Resources
Exercises
- Take an existing Swift file from one of your projects and add proper documentation to all public interfaces.
- Document a complex function with multiple parameters, return values, and possible errors.
- Generate documentation from your Swift code using one of the documentation generation tools mentioned above.
- Create a protocol with well-documented requirements, then implement a conforming type with appropriate documentation.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)