docs: 补充注释、修正过时文档、清理重复内容
源码注释: - 为 ~60 个 Swift 文件补充缺失的 doc comment(file header、类型、属性、方法) - 修正 4 处错误注释:翻页模式数量、搜索行为描述、手势识别器描述、悬空文档块 文档维护: - 删除重复文档:WXRead/读书EPUB阅读器实现架构.md(与微信读书版完全一致) - 合并重叠文档:阅读器规划.md → 阅读器功能开发计划.md(单一真值) - 修正过时内容:所有文档中"四种翻页模式"→"三种",移除 horizontalCoverScroll - 更新架构图:补齐 EPUBUI/ReaderController、Paging/、Typesetter/ 等子目录 - 更新 index.md 索引:新增开发计划和架构对比文档引用
This commit is contained in:
@@ -1,6 +1,17 @@
|
||||
//
|
||||
// RDReaderPreloadController.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:页面预加载控制器,负责提前渲染即将显示的页面视图以减少翻页卡顿。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 页面预加载控制器
|
||||
/// 负责管理页面视图的预加载和缓存,在当前页面基础上提前渲染前后若干页,
|
||||
/// 以减少翻页时的等待时间。支持仿真翻页和滚动模式下的不同复用策略。
|
||||
final class RDReaderPreloadController {
|
||||
/// 预加载半径,表示在当前页前后各预加载的页数,默认为 1
|
||||
var radius: Int = 1
|
||||
|
||||
private let preloadHostView = UIView()
|
||||
@@ -8,6 +19,7 @@ final class RDReaderPreloadController {
|
||||
private var pageCurlCachedViews: [Int: UIView] = [:]
|
||||
private var cacheSignature: CacheSignature?
|
||||
|
||||
/// 预加载环境参数,封装翻页模式、屏幕方向、页面尺寸等上下文信息
|
||||
struct Environment {
|
||||
let displayType: RDReaderView.DisplayType
|
||||
let isLandscape: Bool
|
||||
@@ -26,10 +38,12 @@ final class RDReaderPreloadController {
|
||||
let boundsSize: CGSize
|
||||
}
|
||||
|
||||
/// 设置预加载宿主视图的 frame
|
||||
func setHostFrame(_ frame: CGRect) {
|
||||
preloadHostView.frame = frame
|
||||
}
|
||||
|
||||
/// 将预加载宿主视图添加到父视图中(如果尚未添加),置于最底层且不可见
|
||||
func ensureHostView(in parentView: UIView) {
|
||||
guard preloadHostView.superview == nil else { return }
|
||||
preloadHostView.isHidden = true
|
||||
@@ -40,10 +54,12 @@ final class RDReaderPreloadController {
|
||||
parentView.insertSubview(preloadHostView, at: 0)
|
||||
}
|
||||
|
||||
/// 根据当前环境初始化缓存签名,用于后续检测环境是否发生变化
|
||||
func initializeSignature(_ environment: Environment) {
|
||||
cacheSignature = currentCacheSignature(environment)
|
||||
}
|
||||
|
||||
/// 清除所有已缓存的页面视图并更新缓存签名
|
||||
func invalidate(environment: Environment) {
|
||||
pageCurlCachedViews.values.forEach { $0.removeFromSuperview() }
|
||||
preloadedPageViews.values.forEach { $0.removeFromSuperview() }
|
||||
@@ -52,6 +68,7 @@ final class RDReaderPreloadController {
|
||||
cacheSignature = currentCacheSignature(environment)
|
||||
}
|
||||
|
||||
/// 获取指定页码的页面视图用于显示,优先复用已缓存的视图
|
||||
func pageViewForDisplay(
|
||||
pageNum: Int,
|
||||
environment: Environment,
|
||||
@@ -63,12 +80,14 @@ final class RDReaderPreloadController {
|
||||
return view
|
||||
}
|
||||
|
||||
/// 取出指定页码的预加载视图并从缓存中移除,供外部复用
|
||||
func takePreloadedView(for pageNum: Int) -> UIView? {
|
||||
let preloaded = preloadedPageViews.removeValue(forKey: pageNum)
|
||||
preloaded?.removeFromSuperview()
|
||||
return preloaded
|
||||
}
|
||||
|
||||
/// 预加载当前页周围指定半径内的页面,清除不再需要的缓存视图
|
||||
func prime(
|
||||
around pageNum: Int,
|
||||
preferredForward: Bool? = nil,
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
//
|
||||
// RDReaderSpreadResolver.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:页面展开(spread)解析器,负责计算双页模式下的页面配对和翻页目标。
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 页面展开解析器
|
||||
/// 处理横屏双页模式下的页码配对逻辑,包括封面页独占、双页对齐、
|
||||
/// 以及相邻页面跳转等计算。
|
||||
struct RDReaderSpreadResolver {
|
||||
/// 判断指定页码是否为全屏独占页面(如封面页在双页模式下独占一屏)
|
||||
func isFullScreenPage(
|
||||
_ pageNum: Int,
|
||||
landscapeDualPageEnabled: Bool,
|
||||
@@ -11,6 +22,8 @@ struct RDReaderSpreadResolver {
|
||||
return pageNum == coverIndex
|
||||
}
|
||||
|
||||
/// 计算指定页码在双页模式下的左右页配对,返回 (左页, 右页?)。
|
||||
/// 封面页独占时单独处理,后续页面按两页一组配对。
|
||||
func dualPagePair(
|
||||
for pageNum: Int,
|
||||
totalPages: Int,
|
||||
@@ -32,6 +45,7 @@ struct RDReaderSpreadResolver {
|
||||
return (left, right)
|
||||
}
|
||||
|
||||
/// 计算从指定页码出发的下一个(或上一个)双页展开的起始页码
|
||||
func adjacentDualPage(
|
||||
from pageNum: Int,
|
||||
totalPages: Int,
|
||||
@@ -49,6 +63,7 @@ struct RDReaderSpreadResolver {
|
||||
return dualPagePair(for: prevEnd, totalPages: totalPages, coverPageIndex: coverPageIndex).left
|
||||
}
|
||||
|
||||
/// 计算下一页(或上一页)的页码,自动根据单页/双页模式选择合适的算法
|
||||
func nextPage(
|
||||
from currentPage: Int,
|
||||
totalPages: Int,
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
//
|
||||
// RDReaderTapRegionHandler.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:点击区域判定处理器,将屏幕点击坐标映射为翻页或工具栏操作事件。
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
/// 点击区域判定处理器
|
||||
/// 将屏幕三等分为左、中、右三个区域,根据点击位置和工具栏可见状态
|
||||
/// 决定触发上一页、下一页还是切换工具栏。
|
||||
struct RDReaderTapRegionHandler {
|
||||
/// 根据点击坐标和视图尺寸,解析点击事件类型
|
||||
/// - 左1/3区域:上一页(工具栏可见时转为 center)
|
||||
/// - 中1/3区域:切换工具栏
|
||||
/// - 右1/3区域:下一页(工具栏可见时转为 center)
|
||||
func resolveTapEvent(
|
||||
point: CGPoint,
|
||||
viewFrame: CGRect,
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
//
|
||||
// RDReaderView+CollectionView.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:UICollectionView 数据源和自定义布局代理实现,处理水平滚动和垂直滚动两种翻页模式。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// UICollectionView 数据源和自定义布局代理实现
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
//
|
||||
// RDReaderView+ContentAccess.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:内容视图注册、复用和页面内容访问,提供类似 UITableView 的 register/dequeueReusable 机制。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 内容视图注册和复用扩展
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
//
|
||||
// RDReaderView+PageCurl.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:UIPageViewController 数据源和代理实现,处理仿真翻页模式下的页面数据供给和翻页事件。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// UIPageViewController 数据源和代理实现
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
//
|
||||
// RDReaderView+ToolView.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:工具栏管理扩展,处理工具栏的显示/隐藏动画、安装和布局约束。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 工具栏管理扩展:处理工具栏的显示/隐藏动画、安装、布局
|
||||
extension RDReaderView {
|
||||
|
||||
/// 点击屏幕中央区域,切换工具栏的显示/隐藏
|
||||
/// 点击屏幕中央区域,切换工具栏的显示/隐藏,带动画效果
|
||||
func tapCenter() {
|
||||
refreshToolViewsFromProviderIfNeeded()
|
||||
isShowToolView = !isShowToolView
|
||||
@@ -50,7 +57,7 @@ extension RDReaderView {
|
||||
}
|
||||
}
|
||||
|
||||
/// 判断点击命中的视图是否在指定工具栏内
|
||||
/// 判断点击命中的视图是否在指定工具栏内,用于决定是否拦截点击事件
|
||||
func isHitView(_ hitView: UIView?, inside toolView: UIView, point: CGPoint) -> Bool {
|
||||
if toolView.frame.contains(point) {
|
||||
return true
|
||||
@@ -60,11 +67,15 @@ extension RDReaderView {
|
||||
return hitView === toolView || hitView.isDescendant(of: toolView)
|
||||
}
|
||||
|
||||
/// 工具栏位置枚举
|
||||
enum ToolViewPosition {
|
||||
/// 顶部工具栏(如标题栏、导航栏)
|
||||
case top
|
||||
/// 底部工具栏(如进度条、操作按钮)
|
||||
case bottom
|
||||
}
|
||||
|
||||
/// 将工具栏安装到指定位置并设置布局约束,已安装则跳过
|
||||
func installToolViewIfNeeded(_ toolView: UIView, position: ToolViewPosition) {
|
||||
guard toolView.superview !== self else { return }
|
||||
|
||||
@@ -97,6 +108,7 @@ extension RDReaderView {
|
||||
}
|
||||
}
|
||||
|
||||
/// 更新顶部和底部工具栏的高度约束,通常在 safeAreaInsets 变化时调用
|
||||
func updateToolViewHeightConstraintsIfNeeded() {
|
||||
topToolViewHeightConstraint?.constant = resolvedToolViewHeight(for: .top)
|
||||
bottomToolViewHeightConstraint?.constant = resolvedToolViewHeight(for: .bottom)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
// 文件职责:核心翻页容器视图,RDReaderView 模块的入口和中枢。
|
||||
// 该文件定义了阅读器的核心 UIView 子类 RDReaderView,负责:
|
||||
// 1. 管理四种翻页模式(仿真翻页、水平滚动、垂直滚动、水平覆盖滚动)
|
||||
// 1. 管理三种翻页模式(仿真翻页、水平滚动、垂直滚动)
|
||||
// 2. 实现手势分区逻辑(左1/3上一页、中1/3工具栏、右1/3下一页)
|
||||
// 3. 支持横屏双页显示(含封面页独占和页码配对算法)
|
||||
// 4. 支持从左往右(LTR)和从右往左(RTL)两种翻页方向
|
||||
@@ -21,7 +21,7 @@ import UIKit
|
||||
|
||||
|
||||
/// 核心翻页容器视图
|
||||
/// RDReaderView 模块的核心类,负责管理四种翻页模式的切换、手势识别、
|
||||
/// RDReaderView 模块的核心类,负责管理三种翻页模式的切换、手势识别、
|
||||
/// 横屏双页显示、页面缓存预加载等核心功能。
|
||||
///
|
||||
/// 使用方式:
|
||||
@@ -31,7 +31,7 @@ import UIKit
|
||||
/// 4. 调用 ``reloadData()`` 刷新数据
|
||||
///
|
||||
/// 支持的功能:
|
||||
/// - 四种翻页模式:pageCurl / horizontalScroll / verticalScroll
|
||||
/// - 三种翻页模式:pageCurl / horizontalScroll / verticalScroll
|
||||
/// - 横屏双页显示(含封面页独占逻辑)
|
||||
/// - RTL 翻页方向支持
|
||||
/// - 手势分区(左翻/工具栏/右翻)
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
//
|
||||
// RDReaderViewProtocols.swift
|
||||
// ReadViewSDK
|
||||
//
|
||||
// 文件职责:阅读器核心协议定义,包括数据源、代理、页面提供者、页面导航等接口。
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 阅读器数据源协议
|
||||
@@ -19,10 +26,15 @@ import UIKit
|
||||
/// 与内容格式无关的统一分页提供者协议。
|
||||
/// 逐步替代面向 EPUB 命名的 ``RDReaderDataSource``,方便后续复用到 PDF 等其他阅读场景。
|
||||
@objc public protocol RDReaderPageProvider: NSObjectProtocol {
|
||||
/// 返回阅读器的总页数
|
||||
func numberOfPages(in readerView: RDReaderView) -> Int
|
||||
/// 返回指定页码的内容视图,支持通过 reusableView 复用已有视图
|
||||
func readerView(_ readerView: RDReaderView, viewForPageAt index: Int, reusableView: UIView?) -> UIView
|
||||
/// 返回指定页码的唯一标识符,用于 UICollectionViewCell 复用
|
||||
@objc optional func pageIdentifier(in readerView: RDReaderView, index: Int) -> String?
|
||||
/// 返回顶部工具栏视图(可选)
|
||||
@objc optional func readerViewTopChrome(_ readerView: RDReaderView) -> UIView?
|
||||
/// 返回底部工具栏视图(可选)
|
||||
@objc optional func readerViewBottomChrome(_ readerView: RDReaderView) -> UIView?
|
||||
}
|
||||
|
||||
@@ -35,9 +47,14 @@ import UIKit
|
||||
@objc optional func readerViewOrientationWillChange(readerView: RDReaderView, isLandscape: Bool)
|
||||
}
|
||||
|
||||
/// 阅读器页面导航协议
|
||||
/// 提供与具体实现无关的页面导航接口,外部可通过此协议控制翻页和刷新。
|
||||
public protocol RDReaderPageNavigating: AnyObject {
|
||||
/// 当前显示的页码
|
||||
var currentPage: Int { get }
|
||||
/// 重新加载所有页面数据
|
||||
func reloadPages()
|
||||
/// 跳转到指定页码,可选是否带动画
|
||||
func transition(to page: Int, animated: Bool)
|
||||
}
|
||||
|
||||
@@ -65,7 +82,10 @@ extension RDReaderView {
|
||||
|
||||
// MARK: - Legacy 适配器
|
||||
|
||||
/// 旧版数据源适配器
|
||||
/// 将 ``RDReaderDataSource`` 协议适配为 ``RDReaderPageProvider``,实现渐进式迁移。
|
||||
final class RDReaderLegacyDataSourceAdapter: NSObject, RDReaderPageProvider {
|
||||
/// 被适配的旧版数据源
|
||||
weak var dataSource: RDReaderDataSource?
|
||||
|
||||
func numberOfPages(in readerView: RDReaderView) -> Int {
|
||||
|
||||
Reference in New Issue
Block a user