155 lines
10 KiB
Markdown
155 lines
10 KiB
Markdown
<!-- refreshed: 2026-05-21 -->
|
||
# 架构概览
|
||
|
||
**分析日期:** 2026-05-21
|
||
|
||
## 系统概述
|
||
|
||
本仓库包含一个 iOS **阅读 SDK**(`RDReaderView`)以及一个用于演示集成的 **Demo App**(`ReadViewDemo`)。Demo 通过 CocoaPods 以本地 `:path` 方式引入 SDK。
|
||
|
||
```text
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ Demo App │
|
||
│ `ReadViewDemo/ReadViewDemo` │
|
||
│ - 列表展示内置 .epub/.txt → push `RDURLReaderController` │
|
||
└───────────────────────────────┬─────────────────────────────────────────┘
|
||
│ uses
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ Public SDK │
|
||
│ `Sources/RDReaderView` │
|
||
│ 入口控制器: │
|
||
│ - `RDURLReaderController`(基于 URL:epub/txt) │
|
||
│ - `RDEPUBReaderController`(EPUB + 外部 TextBook) │
|
||
│ 核心视图: │
|
||
│ - `RDReaderView`(仿真翻页 / 横向 / 纵向模式) │
|
||
└───────────────┬───────────────────────────┬─────────────────────────────┘
|
||
│ │
|
||
▼ ▼
|
||
┌───────────────────────────┐ ┌─────────────────────────────────────────┐
|
||
│ EPUBCore │ │ EPUBTextRendering │
|
||
│ `Sources/RDReaderView/ │ │ `Sources/RDReaderView/EPUBTextRendering`│
|
||
│ EPUBCore` │ │ - 从 .txt 构建 `RDEPUBTextBook` │
|
||
│ - 解析/解压 EPUB │ │ - 文本章节渲染/搜索 │
|
||
│ - spine/TOC/location 模型 │ └─────────────────────────────────────────┘
|
||
│ - 基于 WKWebView 分页 │
|
||
│ - 资源解析/寻址 │
|
||
└───────────────┬───────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ EPUBUI │
|
||
│ `Sources/RDReaderView/EPUBUI` │
|
||
│ - 阅读器 UX:工具栏/主题/设置 │
|
||
│ - 默认持久化(UserDefaults) │
|
||
│ - 协调 parser + paginator + RDReaderView │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## 组件职责
|
||
|
||
| 组件 | 职责 | 文件 |
|
||
|---|---|---|
|
||
| `RDURLReaderController` | 面向“URL 打开”的顶层入口;根据后缀路由 epub vs txt;当分页失败时回退为纯文本展示 | `Sources/RDReaderView/RDURLReaderController.swift` |
|
||
| `RDEPUBReaderController` | 主阅读器控制器;协调解析/分页,连接 `RDReaderView`;管理阅读状态、选择/高亮/书签、工具视图等 | `Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` |
|
||
| `RDReaderView` | 分页容器视图,支持仿真翻页与滚动模式;通过 data source 获取页面视图并回调当前页变化 | `Sources/RDReaderView/RDReaderView.swift` |
|
||
| `RDEPUBParser` | 负责解析 `.epub`(container.xml + OPF);构建 manifest/spine/TOC;产出 `RDEPUBPublication` | `Sources/RDReaderView/EPUBCore/RDEPUBParser.swift` |
|
||
| `RDEPUBPublication` | 对解析后的 publication 做只读封装(metadata/spine/TOC/资源解析、fixed-layout 判定等) | `Sources/RDReaderView/EPUBCore/RDEPUBPublication.swift` |
|
||
| `RDEPUBPaginator` | 以 `WKWebView` 测量并生成分页信息(章节页范围、CFI 映射等) | `Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift` |
|
||
| `RDEPUBReadingSession` | 阅读会话状态(当前章节/页、分页缓存、交互状态等),为 UI 层提供数据 | `Sources/RDReaderView/EPUBCore/RDEPUBReadingSession.swift` |
|
||
| `RDEPUBReaderPersistence` | 阅读器持久化协议(位置/设置/书签/高亮等),默认实现使用 UserDefaults | `Sources/RDReaderView/EPUBUI/RDEPUBReaderPersistence.swift` |
|
||
|
||
> 备注:实际类型与职责以代码为准;上表按文件职责做抽象总结。
|
||
|
||
## 分层结构
|
||
|
||
**Demo App 层:**
|
||
- 目的:展示集成方式与最小化书籍选择 UX。
|
||
- 位置:`ReadViewDemo/ReadViewDemo`
|
||
- 依赖:本地 path 的 `RDReaderView` pod、UIKit。
|
||
|
||
**SDK UI 层(Reader UX):**
|
||
- 目的:阅读器控制器 UX + 设置持久化 + 工具视图。
|
||
- 位置:`Sources/RDReaderView/EPUBUI`
|
||
- 依赖:`EPUBCore`、`EPUBTextRendering`、`RDReaderView`。
|
||
|
||
**SDK View 层(分页容器):**
|
||
- 目的:页面呈现模式(翻页/滚动)与手势/工具栏显示控制。
|
||
- 位置:`Sources/RDReaderView/RDReaderView.swift`、`Sources/RDReaderView/RDReaderFlowLayout.swift`
|
||
- 依赖:UIKit。
|
||
|
||
**SDK Core 层(EPUB 解析/分页/状态):**
|
||
- 目的:解析 EPUB 结构、资源寻址、分页计算、导航状态。
|
||
- 位置:`Sources/RDReaderView/EPUBCore`
|
||
- 依赖:Foundation、WebKit(分页/导航)、ZIPFoundation(解压;通过 Podspec 依赖)。
|
||
|
||
**SDK 文本渲染层:**
|
||
- 目的:为纯文本输入构建分页结构并提供渲染/搜索能力。
|
||
- 位置:`Sources/RDReaderView/EPUBTextRendering`
|
||
- 依赖:UIKit/Foundation(以及通过 Podspec 依赖的 DTCoreText 相关能力)。
|
||
|
||
## 数据流
|
||
|
||
### 主路径(通过 URL 打开书籍)
|
||
|
||
1. Demo 选择文件并 push reader(`ReadViewDemo/ReadViewDemo/ViewController.swift`)。
|
||
2. `RDURLReaderController` 根据扩展名分发(`Sources/RDReaderView/RDURLReaderController.swift`)。
|
||
3. 对 EPUB:`RDEPUBReaderController` 开始加载,解析 publication,并为当前视口执行分页(`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift`)。
|
||
4. 分页由 `RDEPUBPaginator`(`WKWebView` 测量)生成 `EPUBPage` / `EPUBChapterInfo` 等快照,供 `RDReaderView` 渲染(`Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift`、`Sources/RDReaderView/EPUBCore/RDEPUBReadingSession.swift`)。
|
||
5. `RDReaderView` 展示页面并输出页切换回调(`Sources/RDReaderView/RDReaderView.swift`)。
|
||
|
||
### 次路径(打开纯文本文件)
|
||
|
||
1. `RDURLReaderController` 使用 `RDPlainTextBookBuilder` 构建 `RDEPUBTextBook`,分页尺寸/样式来自 `RDEPUBReaderConfiguration`(`Sources/RDReaderView/RDURLReaderController.swift`、`Sources/RDReaderView/EPUBTextRendering/RDPlainTextBookBuilder.swift`)。
|
||
2. `RDEPUBReaderController` 以 “external TextBook” 模式运行,复用相同的阅读器 UX 与持久化链路(`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift`)。
|
||
|
||
**状态管理:**
|
||
- 内存态主要由 `RDEPUBReadingSession` 与 `RDEPUBReaderController` 维护。
|
||
- 默认持久化为 UserDefaults(`RDEPUBUserDefaultsPersistence`,见 `Sources/RDReaderView/EPUBUI/RDEPUBReaderPersistence.swift`)。
|
||
|
||
## 入口点
|
||
|
||
**SDK:**
|
||
- `RDURLReaderController`:URL 入口,封装 epub/txt 分支(`Sources/RDReaderView/RDURLReaderController.swift`)。
|
||
- `RDEPUBReaderController`:可直接打开 epub URL,或读取已构建的 `RDEPUBTextBook`(`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift`)。
|
||
- `RDReaderView`:可复用的分页视图(`Sources/RDReaderView/RDReaderView.swift`)。
|
||
|
||
**Demo:**
|
||
- UIKit 生命周期(`ReadViewDemo/ReadViewDemo/AppDelegate.swift`、`ReadViewDemo/ReadViewDemo/SceneDelegate.swift`)。
|
||
|
||
## 架构约束
|
||
|
||
- **平台:** iOS 15+(`RDReaderView.podspec` 中 `s.platform = :ios, "15.0"`)。
|
||
- **视口耦合:** 分页与视口大小/insets 强耦合,视口变化会触发重新分页(`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift`)。
|
||
- **WebKit 依赖:** 可重排 EPUB 的分页使用离屏、非持久化的 `WKWebView`(`Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift`)。
|
||
|
||
## 错误处理
|
||
|
||
**策略:** URL 入口采用“尽量可用”的 fail-soft 体验;Reader Controller 提供可见的 loading/error UI。
|
||
|
||
**模式:**
|
||
- URL 入口在文本分页失败时回退为 `UITextView`(`Sources/RDReaderView/RDURLReaderController.swift`)。
|
||
- Parser 通过 `RDEPUBParserError` 抛出类型化错误(`Sources/RDReaderView/EPUBCore/RDEPUBModels.swift`)。
|
||
|
||
## Evidence(关键证据)
|
||
|
||
检查过的关键文件:
|
||
- `RDReaderView.podspec`
|
||
- `Podfile`
|
||
- `ReadViewDemo/ReadViewDemo.xcworkspace/contents.xcworkspacedata`
|
||
- `ReadViewDemo/ReadViewDemo.xcodeproj/project.pbxproj`
|
||
- `ReadViewDemo/ReadViewDemo/AppDelegate.swift`
|
||
- `ReadViewDemo/ReadViewDemo/SceneDelegate.swift`
|
||
- `ReadViewDemo/ReadViewDemo/ViewController.swift`
|
||
- `Sources/RDReaderView/RDURLReaderController.swift`
|
||
- `Sources/RDReaderView/RDReaderView.swift`
|
||
- `Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift`
|
||
- `Sources/RDReaderView/EPUBCore/RDEPUBParser.swift`
|
||
- `Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift`
|
||
- `Sources/RDReaderView/EPUBCore/RDEPUBPublication.swift`
|
||
- `Sources/RDReaderView/EPUBCore/RDEPUBReadingSession.swift`
|
||
|
||
---
|
||
|
||
*架构分析:2026-05-21*
|