ReadViewSDK/Doc/EPUBUI_CODE_REFERENCE.md
shenlei d7fcda345d refactor: rename RDReaderView -> RDEpubReaderView, update pod config and docs
- Rename source module from RDReaderView to RDEpubReaderView
- Move all source files from Sources/RDReaderView/ to Sources/RDEpubReaderView/
- Update podspec: RDReaderView.podspec -> RDEpubReaderView.podspec
- Update Podfile, demo project, and CocoaPods config for new pod name
- Delete old RDReaderView pod support files from ReadViewDemo/Pods
- Add new RDEpubReaderView pod support files
- Update documentation (API ref, architecture, UML, conventions, etc.)
- Add FixedLayoutRotationTests
- Update .gitignore: exclude .DS_Store, manual unpack backups, _ssoft-output
2026-07-10 19:44:53 +09:00

732 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EPUBUI 模块代码级参考文档
> 最后更新2026-06-18
---
## 1. 模块概述
`EPUBUI` 是 ReadViewSDK 的**用户界面层**,位于架构最顶层。它包含阅读器控制器、协调器模式、章节运行时系统、设置面板、文本页面渲染和标注管理等子系统。
**文件清单(~60 个 Swift 文件):**
| 子系统 | 目录 | 核心文件 | 职责 |
|--------|------|----------|------|
| **阅读器控制器** | `EPUBUI/` | `RDEPUBReaderController*.swift` | 主控制器及其扩展 |
| **协调器** | `ReaderController/` | `RDEPUBReader*Coordinator.swift` | 各功能域协调器 |
| **运行时** | `ReaderController/` | `RDEPUBReaderRuntime.swift`, `RDEPUBReaderContext.swift` | 运行时状态与依赖 |
| **章节运行时** | `ReaderController/ChapterRuntime/` | `RDEPUBChapter*.swift` | 按需加载、缓存、页图 |
| **设置** | `Settings/` | `RDEPUBReaderSettings*.swift` | 配置、主题、设置面板 |
| **文本页面** | `TextPage/` | `RDEPUBTextContentView*.swift` | 原生文本渲染页面 |
| **UI 组件** | `EPUBUI/` | `RDEPUBReader*ToolView.swift` | 工具栏、搜索栏、目录 |
| **笔记弹层** | `Notes/` | `RDEPUBNotePopup*.swift` | 脚注弹层 |
| **WebView** | `EPUBUI/` | `RDEPUBWebContentView.swift` | WebView 内容页面 |
---
## 2. 阅读器控制器
### 2.1 RDEPUBReaderController
**文件:** `RDEPUBReaderController.swift` + 扩展文件
主控制器,`UIViewController` 子类,是整个阅读器的入口。
```swift
public final class RDEPUBReaderController: UIViewController {
public weak var delegate: RDEPUBReaderDelegate?
public var configuration: RDEPUBReaderConfiguration // 配置(变化时自动重新分页/刷新)
public var currentLocation: RDEPUBLocation? // 当前阅读位置
public var currentPageNumber: Int? // 当前页码1-based
public var currentSelection: RDEPUBSelection? // 当前选中文本
public var highlights: [RDEPUBHighlight] // 高亮列表
public var bookmarks: [RDEPUBBookmark] // 书签列表
public var annotations: [RDEPUBAnnotation] // 标注列表(高亮+书签,按时间排序)
public var tableOfContents: [EPUBTableOfContentsItem] // 目录树
public var flattenedTableOfContents: [RDEPUBReaderTableOfContentsItem] // 扁平化目录
let epubURL: URL // EPUB 文件路径
let persistence: RDEPUBReaderPersistence? // 持久化代理
let dependencies: RDEPUBReaderDependencies // 依赖注入
let readerView = RDEpubReaderView() // 翻页容器
}
```
**扩展文件职责:**
| 文件 | 职责 |
|------|------|
| `RDEPUBReaderController+PublicAPI.swift` | 公开 API跳转、搜索、标注、书签 |
| `RDEPUBReaderController+DataSource.swift` | `RDEpubReaderPageProvider` 实现 |
| `RDEPUBReaderController+ContentDelegates.swift` | WebView/TextContentView 代理路由 |
| `RDEPUBReaderController+LocationResolution.swift` | 页码/位置解析、阅读状态同步 |
| `RDEPUBReaderController+ExternalLinks.swift` | 外部链接处理(白名单、确认弹窗) |
| `RDEPUBReaderController+AttachmentTooltip.swift` | 附件 alt 文本 tooltip 展示 |
| `RDEPUBReaderController+RenderSupport.swift` | 渲染辅助WebView/TextContent 创建) |
| `RDEPUBReaderController+RuntimeBridge.swift` | Runtime 桥接 |
| `RDEPUBReaderController+TableOfContents.swift` | 目录处理 |
### 2.2 RDEPUBReaderDelegate
**文件:** `RDEPUBReaderDelegate.swift`
```swift
public protocol RDEPUBReaderDelegate: AnyObject {
func epubReader(_ reader: UIViewController, didOpen publication: RDEPUBPublication)
func epubReader(_ reader: UIViewController, didUpdateLocation location: RDEPUBLocation)
func epubReaderDidReachEnd(_ reader: UIViewController)
func epubReader(_ reader: UIViewController, didChangeSelection selection: RDEPUBSelection?)
func epubReader(_ reader: UIViewController, didUpdateHighlights highlights: [RDEPUBHighlight])
func epubReader(_ reader: UIViewController, didUpdateBookmarks bookmarks: [RDEPUBBookmark])
func epubReader(_ reader: UIViewController, didUpdateSearchResult result: RDEPUBSearchResult?)
func epubReader(_ reader: UIViewController, didChangeCurrentSearchMatch match: RDEPUBSearchMatch?)
func epubReader(_ reader: UIViewController, didUpdateCurrentTableOfContentsItem item: RDEPUBReaderTableOfContentsItem?)
func epubReader(_ reader: UIViewController, didActivateExternalLink url: URL)
func epubReader(_ reader: UIViewController, shouldOpenExternalURL url: URL) -> Bool
func epubReader(_ reader: UIViewController, didFailWithError error: Error)
func epubReader(_ reader: UIViewController, configureTopToolView topToolView: RDEPUBReaderTopToolView)
}
```
所有方法均有默认空实现。
### 2.3 RDEPUBReaderPersistence
**文件:** `RDEPUBReaderPersistence.swift`
持久化协议,由宿主 App 实现。
```swift
public protocol RDEPUBReaderPersistence: AnyObject {
func loadLocation(for bookIdentifier: String) -> RDEPUBLocation?
func saveLocation(_ location: RDEPUBLocation, for bookIdentifier: String)
func loadBookmarks(for bookIdentifier: String) -> [RDEPUBBookmark]
func saveBookmarks(_ bookmarks: [RDEPUBBookmark], for bookIdentifier: String)
func loadHighlights(for bookIdentifier: String) -> [RDEPUBHighlight]
func saveHighlights(_ highlights: [RDEPUBHighlight], for bookIdentifier: String)
}
```
---
## 3. 运行时与上下文
### 3.1 RDEPUBReaderContext
**文件:** `ReaderController/RDEPUBReaderContext.swift`
阅读器的共享上下文,持有所有运行时状态。协调器通过 `unowned` 引用访问。
```swift
final class RDEPUBReaderContext {
weak var controller: RDEPUBReaderController?
weak var readerView: RDEpubReaderView?
var dependencies: RDEPUBReaderDependencies
var runtime: RDEPUBReaderRuntime?
// 解析状态
var parser: RDEPUBParser?
var publication: RDEPUBPublication?
var readingSession: RDEPUBReadingSession?
var textBook: RDEPUBTextBook?
var bookPageMap: RDEPUBBookPageMap?
// 标注状态
var activeBookmarks: [RDEPUBBookmark]
var activeHighlights: [RDEPUBHighlight]
var currentBookIdentifier: String?
var selectionState: RDEPUBSelectionState
var currentSelection: RDEPUBSelection?
// 搜索状态
var searchState: RDEPUBSearchState?
}
```
### 3.2 RDEPUBReaderDependencies
**文件:** `ReaderController/RDEPUBReaderDependencies.swift`
依赖注入容器,支持测试替身。
```swift
public struct RDEPUBReaderDependencies {
public var environment: any RDEPUBReaderDisplayEnvironment
public var makeParser: () -> RDEPUBParser
public var makePaginator: () -> RDEPUBPaginator
public var makeTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextBookCache?, RDEPUBTextLayoutConfig) -> RDEPUBTextBookBuilder
public var makePlainTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextLayoutConfig) -> RDEpubPlainTextBookBuilder
public var makeTextRenderer: (RDEPUBTextRenderingEngine) -> RDEPUBTextRenderer
public static var live: RDEPUBReaderDependencies // 默认实现
}
```
### 3.3 RDEPUBReaderRuntime
**文件:** `ReaderController/RDEPUBReaderRuntime.swift`
运行时管理器,持有所有协调器和子系统。
```swift
final class RDEPUBReaderRuntime {
lazy var chapterRuntimeStore = RDEPUBChapterRuntimeStore()
lazy var summaryDiskCache: RDEPUBChapterSummaryDiskCache
lazy var chapterLoader: RDEPUBChapterLoader
lazy var pageResolver: RDEPUBPageResolver
lazy var loadCoordinator: RDEPUBReaderLoadCoordinator
lazy var paginationCoordinator: RDEPUBReaderPaginationCoordinator
lazy var locationCoordinator: RDEPUBReaderLocationCoordinator
lazy var searchCoordinator: RDEPUBReaderSearchCoordinator
lazy var chromeCoordinator: RDEPUBReaderChromeCoordinator
lazy var annotationCoordinator: RDEPUBReaderAnnotationCoordinator
lazy var viewportMonitor: RDEPUBReaderViewportMonitor
lazy var jumpSessionManager: RDEPUBJumpSessionManager
lazy var backgroundPriorityManager: RDEPUBBackgroundPriorityManager
lazy var backgroundCoverageStore: RDEPUBBackgroundCoverageStore
lazy var reconciliationCoordinator: RDEPUBPageMapReconciliationCoordinator
var isSettingsPanelOpen: Bool
var needsFullRepaginationAfterSettingsClose: Bool
}
```
---
## 4. 协调器子系统
采用 **Coordinator 模式**,每个功能域由独立的协调器管理。
### 4.1 RDEPUBReaderLoadCoordinator
**文件:** `ReaderController/RDEPUBReaderLoadCoordinator.swift`
负责初始加载流程:解析 EPUB → 创建 Publication → 恢复阅读位置。
```swift
final class RDEPUBReaderLoadCoordinator {
func startInitialLoadIfNeeded() // 开始初始加载
func loadPublication() // 解析 EPUB 文件
func applyParsedPublication(...) // 应用解析结果
}
```
### 4.2 RDEPUBReaderPaginationCoordinator
**文件:** `ReaderController/RDEPUBReaderPaginationCoordinator.swift`
负责分页调度WebView 分页 → 文本构建 → 页图生成。
```swift
final class RDEPUBReaderPaginationCoordinator {
func startPagination(...) // 开始分页
func applyPageCounts(...) // 应用页数结果
func repaginatePreservingCurrentLocation() // 重新分页(保持位置)
}
```
### 4.3 RDEPUBReaderLocationCoordinator
**文件:** `ReaderController/RDEPUBReaderLocationCoordinator.swift`
负责位置管理:恢复位置、记录位置变化、目录跳转。
```swift
final class RDEPUBReaderLocationCoordinator {
func restoreReadingLocation(_ location: RDEPUBLocation, animated: Bool, ...) -> Bool
func currentVisibleLocation() -> RDEPUBLocation?
func recordPageChangeIfNeeded()
}
```
### 4.4 RDEPUBReaderSearchCoordinator
**文件:** `ReaderController/RDEPUBReaderSearchCoordinator.swift`
负责搜索管理:执行搜索、导航到匹配项、清除搜索。
```swift
final class RDEPUBReaderSearchCoordinator {
func search(keyword: String)
func searchNext() -> Bool
func searchPrevious() -> Bool
func selectSearchMatch(at index: Int) -> Bool
func clearSearch()
}
```
### 4.5 RDEPUBReaderChromeCoordinator
**文件:** `ReaderController/RDEPUBReaderChromeCoordinator.swift`
负责 UI Chrome工具栏、搜索栏的创建和状态更新。
```swift
final class RDEPUBReaderChromeCoordinator {
func makeTopToolView() -> RDEPUBReaderTopToolView
func makeBottomToolView() -> RDEPUBReaderBottomToolView
func updateReaderChrome()
func toggleSearchBar()
func presentTableOfContents()
func presentSettings()
}
```
### 4.6 RDEPUBReaderAnnotationCoordinator
**文件:** `ReaderController/RDEPUBReaderAnnotationCoordinator.swift`
负责标注管理:高亮、书签的增删改查。
```swift
final class RDEPUBReaderAnnotationCoordinator {
func addHighlight(from selection: RDEPUBSelection?, color: String, note: String?) -> RDEPUBHighlight?
func removeHighlight(withID id: String)
func addBookmark(for location: RDEPUBLocation, ...) -> RDEPUBBookmark?
func removeBookmark(withID id: String)
func toggleBookmark() -> Bool
func updateCurrentSelection(_ selection: RDEPUBSelection?)
}
```
---
## 5. 章节运行时子系统
**目录:** `ReaderController/ChapterRuntime/`
按需加载章节、管理章节缓存、维护全书页图。
### 5.1 RDEPUBChapterRuntimeStore
**文件:** `ChapterRuntime/RDEPUBChapterRuntimeStore.swift`
章节数据的核心存储,管理内存缓存和窗口。
```swift
final class RDEPUBChapterRuntimeStore {
let chapterLoadQueue: DispatchQueue // 后台加载队列
private(set) var currentSpineIndex: Int?
private(set) var windowSpineIndices: [Int] // 当前窗口内的 spine 索引
func chapterData(for spineIndex: Int) -> RDEPUBRuntimeChapter?
func insertChapter(_ chapter: RDEPUBRuntimeChapter)
func setCurrentChapter(spineIndex: Int, totalSpineCount: Int, windowRadius: Int)
func evictableSpineIndices() -> [Int]
func evict(spineIndex: Int)
}
```
### 5.2 RDEPUBChapterLoader
**文件:** `ChapterRuntime/RDEPUBChapterLoader.swift`
章节按需加载器,支持优先级和磁盘摘要缓存。
```swift
final class RDEPUBChapterLoader {
enum LoadPriority {
case navigation // 导航(最高优先级)
case preview // 预览
case prefetch // 预取(最低优先级)
}
func loadChapter(
spineIndex: Int,
store: RDEPUBChapterRuntimeStore,
priority: LoadPriority,
completion: @escaping (Result<RDEPUBRuntimeChapter, Error>) -> Void
)
}
```
**加载流程:**
1. 检查内存缓存(`RDEPUBChapterDataCache`
2. 检查页数缓存(`RDEPUBPageCountCache`
3. 检查磁盘摘要缓存(`RDEPUBChapterSummaryDiskCache`
4. 构建章节(排版 + 分页)
5. 写入缓存
### 5.3 RDEPUBChapterWindowCoordinator
**文件:** `ChapterRuntime/RDEPUBChapterWindowCoordinator.swift`
管理章节窗口(当前章 + 前后各 N 章),协调加载和驱逐。
```swift
final class RDEPUBChapterWindowCoordinator {
private(set) var currentSnapshot: RDEPUBChapterWindowSnapshot?
var onSnapshotChanged: ((RDEPUBChapterWindowSnapshot) -> Void)?
func openBook(at targetSpineIndex: Int, restoreChapterOffset: Int?)
func navigateToChapter(at spineIndex: Int)
}
```
### 5.4 RDEPUBBookPageMap
**文件:** `ChapterRuntime/RDEPUBBookPageMap.swift`
全书页图,映射绝对页码 ↔ spine 索引 + 本地页码。
```swift
struct RDEPUBBookPageMap {
let entries: [RDEPUBBookPageMapEntry]
let totalPages: Int
func absolutePageIndex(spineIndex: Int, localPageIndex: Int) -> Int?
func spineIndex(forAbsolutePage absolutePage: Int) -> Int?
func localPageIndex(forAbsolutePage absolutePage: Int) -> Int?
func chapterIndex(forSpineIndex spineIndex: Int) -> Int?
}
```
### 5.5 RDEPUBPageResolver
**文件:** `ChapterRuntime/RDEPUBPageResolver.swift`
将绝对页码解析为具体的页面数据。
```swift
final class RDEPUBPageResolver {
func resolvePage(absolutePageIndex: Int) -> RDEPUBResolvedPage?
}
struct RDEPUBResolvedPage {
let page: RDEPUBTextPage
let chapter: RDEPUBRuntimeChapter
let chapterIndex: Int
}
```
### 5.6 其他 ChapterRuntime 组件
| 文件 | 职责 |
|------|------|
| `RDEPUBRuntimeChapter.swift` | 运行时章节模型(包含分页后的页面列表) |
| `RDEPUBRuntimePageCount.swift` | 页数缓存模型 |
| `RDEPUBChapterDataCache.swift` | 章节数据内存缓存NSCache |
| `RDEPUBPageCountCache.swift` | 页数缓存 |
| `RDEPUBChapterCacheKey.swift` | 缓存键pageSize + fontSize + lineHeight |
| `RDEPUBChapterSummaryDiskCache.swift` | 章节摘要磁盘缓存 |
| `RDEPUBChapterWindowSnapshot.swift` | 窗口快照(当前可见章节集合) |
| `RDEPUBChapterLocation.swift` | 章节位置模型 |
| `RDEPUBChapterOffsetMap.swift` | 章节偏移映射 |
| `RDEPUBBackgroundTrace.swift` | 后台任务追踪日志 |
| `RDEPUBMetadataParseWorker.swift` | 后台元数据解析 worker |
| `RDEPUBMetadataParseCancellationController.swift` | 解析取消控制器 |
---
## 6. 设置子系统
**目录:** `Settings/`
### 6.1 RDEPUBReaderConfiguration
**文件:** `Settings/RDEPUBReaderConfiguration.swift`
阅读器配置模型。
```swift
public struct RDEPUBReaderConfiguration: Equatable {
public var fontSize: CGFloat
public var lineHeightMultiple: CGFloat
public var fontChoice: RDEPUBReaderFontChoice
public var numberOfColumns: Int
public var columnGap: CGFloat
// ... 更多配置项
}
public enum RDEPUBReaderFontChoice: String, Codable, CaseIterable {
case system // 系统字体
case serif // 宋体
case rounded // 圆体
case monospaced // 等宽
}
public enum RDEPUBTextRenderingEngine: Equatable {
case dtCoreText
}
```
### 6.2 RDEPUBReaderSettings
**文件:** `Settings/RDEPUBReaderSettings.swift`
设置状态管理。
### 6.3 RDEPUBReaderSettingsViewController
**文件:** `Settings/RDEPUBReaderSettingsViewController.swift`
设置面板 VC字体大小、行高、字体选择、主题等
### 6.4 RDEPUBReaderTheme
**文件:** `Settings/RDEPUBReaderTheme.swift`
主题定义(日间/夜间/护眼等)。
---
## 7. 文本页面子系统
**目录:** `TextPage/`
原生文本渲染模式(`textReflowable`)的页面视图。
### 7.1 RDEPUBTextContentView
**文件:** `TextPage/RDEPUBTextContentView.swift`
文本内容视图,使用 CoreText 渲染 `NSAttributedString`
```swift
final class RDEPUBTextContentView: UIView, UIGestureRecognizerDelegate {
weak var delegate: RDEPUBTextContentViewDelegate?
func configure(page: RDEPUBTextPage, ...)
func applyHighlights(_ highlights: [RDEPUBHighlight])
func applySearchState(_ state: RDEPUBSearchState?)
}
```
### 7.2 RDEPUBTextPageRenderView
**文件:** `TextPage/RDEPUBTextPageRenderView.swift`
CoreText 渲染视图,绘制 `NSAttributedString` 到屏幕上。
### 7.3 RDEPUBTextAnnotationOverlay
**文件:** `TextPage/RDEPUBTextAnnotationOverlay.swift`
标注叠加层,绘制高亮和下划线。
### 7.4 RDEPUBSelectionOverlayView
**文件:** `TextPage/RDEPUBSelectionOverlayView.swift`
文本选择叠加层(选择手柄)。
### 7.5 RDEPUBTextSelectionController
**文件:** `TextPage/RDEPUBTextSelectionController.swift`
文本选择手势控制器。
### 7.6 RDEPUBPageInteractionController
**文件:** `TextPage/RDEPUBPageInteractionController.swift`
页面交互控制器(长按选择、点击标注等)。
### 7.7 RDEPUBPageLayoutSnapshot
**文件:** `TextPage/RDEPUBPageLayoutSnapshot.swift`
页面布局快照(用于选择定位)。
### 7.8 RDEPUBTextPageDecorationView
**文件:** `TextPage/RDEPUBTextPageDecorationView.swift`
页面装饰视图(页码、页眉等)。
---
## 8. UI 组件
### 8.1 工具栏
| 文件 | 职责 |
|------|------|
| `RDEPUBReaderTopToolView.swift` | 顶部工具栏(返回、搜索、书签) |
| `RDEPUBReaderBottomToolView.swift` | 底部工具栏(目录、书签、高亮、设置) |
| `RDEPUBReaderToolView.swift` | 工具栏基类 |
### 8.2 搜索栏
**文件:** `RDEPUBReaderSearchBarView.swift`
搜索输入栏(输入框 + 上一个/下一个 + 关闭)。
### 8.3 目录
**文件:** `RDEPUBReaderChapterListController.swift`
目录列表 VC支持多级目录展开。
**文件:** `RDEPUBReaderTableOfContentsItem.swift`
目录项模型。
### 8.4 高亮管理
**文件:** `RDEPUBReaderHighlightsViewController.swift`
高亮列表 VC。
### 8.5 笔记弹层
**目录:** `Notes/`
| 文件 | 职责 |
|------|------|
| `RDEPUBNotePopupCoordinator.swift` | 脚注弹层协调器 |
| `RDEPUBNotePopupViewController.swift` | 脚注弹层 VC |
### 8.6 WebView 内容视图
**文件:** `RDEPUBWebContentView.swift`
WebView 模式的内容页面视图。
### 8.7 装饰叠加层
**文件:** `RDEPUBWebDecorationOverlayView.swift`
WebView 模式的装饰叠加层(高亮、搜索高亮)。
---
## 9. 状态模型
### 9.1 RDEPUBSelectionState
```swift
enum RDEPUBSelectionState: Equatable {
case idle // 无选择
case selecting(anchor: Int) // 选择中
case selected(RDEPUBSelection) // 已选择
case committingAction(RDEPUBSelection, action: RDEPUBAnnotationMenuAction) // 执行操作中
}
```
### 9.2 RDEPUBReaderUIState
```swift
struct RDEPUBReaderUIState {
let canToggleBookmark: Bool
let hasBookmarkAtCurrentLocation: Bool
let canShowBookmarks: Bool
let canAddHighlight: Bool
let canShowHighlights: Bool
let showsTableOfContents: Bool
let allowsHighlights: Bool
let showsSettingsPanel: Bool
}
```
### 9.3 RDEPUBViewportTypes
**文件:** `RDEPUBViewportTypes.swift`
视口相关模型。
---
## 10. 其他组件
### 10.1 RDEPUBReaderViewportMonitor
**文件:** `ReaderController/RDEPUBReaderViewportMonitor.swift`
视口变化监听器(旋转、尺寸变化)。
### 10.2 RDEPUBJumpSession
**文件:** `ReaderController/RDEPUBJumpSession.swift`
跳转会话管理(远距跳转时的加载状态)。
### 10.3 RDEPUBBackgroundPriorityPolicy
**文件:** `ReaderController/RDEPUBBackgroundPriorityPolicy.swift`
后台加载优先级策略。
### 10.4 RDEPUBBackgroundCoverageStore
**文件:** `ReaderController/RDEPUBBackgroundCoverageStore.swift`
后台加载覆盖范围追踪。
### 10.5 RDEPUBPageMapReconciliationCoordinator
**文件:** `ReaderController/RDEPUBPageMapReconciliationCoordinator.swift`
页图协调器(按需分页与全量分页的结果合并)。
### 10.6 RDEpubURLReaderController
**文件:** `RDEpubURLReaderController.swift`
URL 阅读器控制器(用于打开单个 URL
### 10.7 UIColor+RDEPUBHex
**文件:** `UIColor+RDEPUBHex.swift`
UIColor 十六进制扩展。
---
## 11. 设计模式总结
| 模式 | 应用 |
|------|------|
| **Coordinator 模式** | 7 个独立协调器分管各功能域 |
| **Context 模式** | `RDEPUBReaderContext` 共享上下文,避免循环依赖 |
| **依赖注入** | `RDEPUBReaderDependencies` 工厂方法注入 |
| **按需加载** | `RDEPUBChapterLoader` 章节级按需加载 |
| **窗口管理** | `RDEPUBChapterWindowCoordinator` 滑动窗口驱逐 |
| **快照管理** | `RDEPUBBookPageMap` 全书页图快照 |
| **状态机** | `RDEPUBSelectionState` 选择状态管理 |
| **磁盘缓存** | `RDEPUBChapterSummaryDiskCache` 章节摘要持久化 |
---
## 12. 数据流图
```
用户打开 EPUB
RDEPUBReaderController.init(epubURL:)
▼ viewDidLoad()
RDEPUBReaderLoadCoordinator.startInitialLoadIfNeeded()
├── RDEPUBParser.parse(epubURL:) → 解析 EPUB
├── RDEPUBPublication 创建
├── 恢复阅读位置persistence.loadLocation
RDEPUBReaderRuntime.applyParsedPublication()
├── 根据 readingProfile 选择渲染模式
│ ├── webInteractive → WebView 分页 → RDEPUBPaginator
│ └── textReflowable → 文本构建 → RDEPUBTextBookBuilder
├── RDEPUBChapterWindowCoordinator.openBook()
│ └── RDEPUBChapterLoader.loadChapter() → 按需加载
├── RDEPUBBookPageMap 生成
└── RDEpubReaderView.transitionToPage() → 显示页面
用户翻页
RDEpubReaderView.currentPage 变化
├── RDEPUBReaderLocationCoordinator.recordPageChangeIfNeeded()
│ └── persistence.saveLocation()
├── RDEPUBChapterWindowCoordinator 检查是否需要加载新章节
└── RDEPUBReaderChromeCoordinator.updateReaderChrome()
```