Elevate your DocC documentation in Xcode
Developer Tools 进阶 25m

提升你的 DocC 文档质量

Elevate your DocC documentation in Xcode

2021年6月8日

在 Apple 官方观看视频

一句话判断

上一场 Session 教你”怎么用 DocC”,这场教你怎么把文档写得让开发者愿意读——重点不是工具本身,而是文档的内容架构和最佳实践。

这场 Session 讲了什么

Session 是 10166(Meet DocC)的进阶篇,聚焦于如何编写高质量的 DocC 文档内容。覆盖了 API 文档注释的结构化编写、Article(文章)的组织方式、Extension 文件的使用、以及如何让文档在 Xcode 的 Documentation Window 中呈现最佳效果。

Session 反复强调一个原则:好的文档不只是描述 API 做了什么(What),更要解释为什么这样设计(Why)和什么时候该用(When)。/// 注释中的第一句话尤其重要——它是 DocC 在 Symbol 页面上显示的摘要(Abstract),应该是一个完整的句子,而不是一个名词短语。比如写”返回当前用户会话的状态”而不是”会话状态”。Session 还介绍了 DocC 的 Extension 文件机制——你可以在不修改源代码的情况下,通过外部 .md 文件给任意 symbol 添加文档,这对于给第三方库或跨模块类型写文档非常实用。

值得深挖的点

Extension 文件的妙用

Extension 文件允许你在源代码之外给任何符号添加文档。文件格式是标准的 DocC Markdown,但使用 ## ``SymbolName``` 的方式关联到具体的类型或方法。这对于几种场景特别有用:给第三方框架的扩展写文档、给自动生成的代码(比如 Core Data 的 NSManagedObject` 子类)写文档、以及将大段的文档从源代码中抽离出来保持代码整洁。

文档的层级结构设计

DocC 的文档有三个层级:Symbol 页面(某个类型或方法的文档)、Article 页面(一篇独立的技术文章)、Topic 页面(按主题聚合的文档集合)。好的文档架构应该让用户可以从 Topic 入口找到相关 Article,再从 Article 跳转到具体的 Symbol。Session 建议每个框架至少写一篇”Overview” Article 作为入口,覆盖核心概念和使用场景,然后在每个 Symbol 的注释中用 <doc:ArticleName> 链接到相关的 Article。

代码片段

/// 从网络获取用户资料。
///
/// 使用指定的用户 ID 从服务器获取完整的用户资料信息。
/// 此方法会在后台线程执行网络请求,不会阻塞当前线程。
///
/// 当你需要获取非当前登录用户的资料时使用此方法。
/// 对于当前用户的资料,请使用 ``fetchCurrentUser()`` ——它会利用本地缓存。
///
/// - Parameters:
///   - userID: 目标用户的唯一标识符
///   - options: 获取选项,控制返回哪些字段。默认返回所有字段。
/// - Returns: 包含用户资料的 ``UserProfile`` 对象
/// - Throws:
///   - ``NetworkError/notFound`` 当用户 ID 不存在时
///   - ``NetworkError/unauthorized`` 当无权访问该用户资料时
///   - ``NetworkError/timeOut`` 当请求超过 30 秒未响应时
///
/// ## 示例
///
/// ```swift
/// do {
///     let profile = try await userService.fetchProfile(
///         userID: "abc123",
///         options: .minimal
///     )
///     print("用户名: \(profile.displayName)")
/// } catch NetworkError.notFound {
///     print("用户不存在")
/// }
/// ```
///
/// > Tip: 如果你需要批量获取多个用户的资料,
/// > 使用 ``fetchProfiles(userIDs:options:)`` 可以减少网络请求次数。
///
/// - Important: 此方法要求用户已登录,否则会抛出 ``NetworkError/unauthorized``。
///
/// - Since: 2.0
/// - SeeAlso: ``fetchCurrentUser()``, ``UserProfile``
public func fetchProfile(userID: String, 
                          options: FetchOptions = .all) async throws -> UserProfile {
    // 实现
}
<!-- Documentation/MyFramework/NetworkGuide.md -->
# 网络请求指南

## 概述

MyFramework 的网络层基于 Swift Concurrency 构建,
所有网络操作都是异步的,使用 `async/await` 语法。

@Row {
    @Column(size: 2) {
        ### 简单请求
        ```swift
        let user = try await service.fetchProfile(userID: "123")
        ```
    }
    @Column(size: 2) {
        ### 批量请求
        ```swift
        async let user = service.fetchProfile(userID: "123")
        async let posts = service.fetchPosts(userID: "123")
        let (profile, feed) = try await (user, posts)
        ```
    }
}

## 主题

### 基础操作

- <doc:AuthenticationGuide>: 认证和令牌管理
- <doc:ErrorHandlingGuide>: 错误处理最佳实践

### 高级用法

- <doc:CachingGuide>: 响应缓存策略
- <doc:RetryStrategy>: 自动重试机制

## 参考

- ``UserService``: 用户相关的网络服务
- ``NetworkError``: 所有可能的网络错误
<!-- Documentation/MyFramework/Extensions/UUID+Documentation.md -->
# ``UUID``

# 为 UUID 添加的扩展文档

## 概述

标准库的 `UUID` 类型没有提供从字符串方便创建的方法。
MyFramework 为此添加了一个扩展。

## 主题

### 创建

- ``UUID/init(hexString:)``
- ``UUID/init(base64Encoded:)``

## 另见

- <doc:FoundationExtensions>

最佳实践

  • 每个公开 API 的文档注释第一行写一个完整的动词句(“做某事”),不要写名词短语。DocC 把第一行作为摘要显示在列表页和搜索结果中。
  • 在 Throws 部分列举所有可能的错误类型,并用行内代码标记。用户最怕的是”不知道这个方法会抛什么错”。
  • > Tip:> Important: 等 callout 突出关键信息。DocC 会用不同颜色渲染这些区块,视觉上很醒目。

还有什么值得关注

  • DocC 支持在文档中嵌入图表和视频,适合 Tutorial 类型的内容。
  • @Snippet 标签可以在多处引用同一个代码片段,减少重复维护。
  • Xcode 13 的 Quick Help(Option+点击)现在会显示更丰富的 DocC 格式内容,包括代码示例和 callout。
WWDC 2021