Files
ReadViewSDK/ReadViewDemo/ReadViewDemoUITests/ReaderUITests/FixedLayoutRotationTests.swift
T
shenleiandClaude Fable 5 1422461224 将 PDF 成品阅读控制器下沉为 RDPDFReaderView SDK,并修复手机横屏单页连续竖滑
SDK 化收尾:
- 新增 RDPDFReaderView 本地 pod(阅读容器、成品控制器、划线/注释、画笔、
  目录/设置面板、主题与持久化契约),Demo 精简为 PDFKit 页面提供者 + 持久化宿主
- Podfile/工程接入 RDPDFReaderView 与 SnapKit,示例书改用 PDF 阅读器示例文件

手机横屏单页竖滑修复:
- cell 高度改为宽度适配后的纸张高度(sizeForItemAt + 宿主按页提供纵横比),
  纵向超出一屏的内容由外层 collectionView 连续滚动承接,不再被裁掉
- 页面内部不再开启同向嵌套的兜底竖向拖动,修复外层滚动被吞、无法滚到下一页
- 修复 applyContentSize 先评估拖动开关后写 contentSize 的顺序缺陷
- 页码按视口中心命中 cell 计算,补 didEndDragging 兜底;旋转重锚点与
  transitionToPage 改用真实布局位置
- 横竖屏同为竖滑时也重建 cell 并刷新全部可见页的适配配置
- 横屏单页点击不再跳页,只显隐工具栏;翻页交给连续竖滑

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 18:49:44 +09:00

102 lines
4.5 KiB
Swift
Raw 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.
import XCTest
/// 固定布局(pre-paginated)书籍的旋转回归:
/// 每次旋转会使预加载缓存签名失效并批量丢弃 WKWebView 页面,
/// 历史上曾因 script message handler 保留环导致 WebView 泄漏累积,
/// 多次旋转后在 CA commit 阶段 abortCA::Render::Encoder::grow)。
final class FixedLayoutRotationTests: XCTestCase {
private let app = XCUIApplication()
override func setUpWithError() throws {
continueAfterFailure = false
XCUIDevice.shared.orientation = .portrait
}
override func tearDownWithError() throws {
XCUIDevice.shared.orientation = .portrait
}
func testFixedLayoutBookSurvivesRepeatedRotation() {
app.launchAndOpenSampleBook(bookTitleQuery: "熊爷爷")
app.waitForReader()
for _ in 0..<3 {
XCUIDevice.shared.orientation = .landscapeLeft
RunLoop.current.run(until: Date().addingTimeInterval(2))
let landscapeState = app.waitForDemoReaderState(
timeout: 5,
description: "固定版式横屏保持单页"
) { $0.pagesPerScreen == 1 }
XCTAssertEqual(landscapeState.pagesPerScreen, 1, "交互型固定版式书横屏不应启用双页")
XCUIDevice.shared.orientation = .portrait
RunLoop.current.run(until: Date().addingTimeInterval(2))
}
XCTAssertEqual(app.state, .runningForeground, "反复旋转后 app 已退出(疑似崩溃)")
app.waitForReader()
}
/// PDF 手机横屏必须在旋转完成的第一轮布局中立即成为全宽单页。
/// 过去 flow layout 继续使用竖屏 itemSize,导致横屏首帧并排露出两页,
/// 只有点击触发下一轮布局后才恢复。
func testPDFLandscapeImmediatelyUsesSingleFullWidthPage() {
app.launchAndOpenSampleBook(
bookTitleQuery: "英汉大词典",
displayType: "pagecurl"
)
app.waitForReader()
XCUIDevice.shared.orientation = .landscapeLeft
let content = app.otherElements[IDs.readerContent].firstMatch
XCTAssertTrue(content.waitForExistence(timeout: 8), "PDF 阅读区域未出现")
let deadline = Date().addingTimeInterval(8)
while Date() < deadline {
let windowWidth = app.windows.firstMatch.frame.width
if windowWidth > 0, abs(content.frame.width - windowWidth) <= 1 {
break
}
RunLoop.current.run(until: Date().addingTimeInterval(0.1))
}
// 等待旋转动画和 PDF 页异步配置完成,避免只验证到过渡中的短暂正确状态。
RunLoop.current.run(until: Date().addingTimeInterval(1.5))
let windowFrame = app.windows.firstMatch.frame
XCTAssertGreaterThan(windowFrame.width, windowFrame.height, "设备没有进入横屏")
XCTAssertEqual(content.frame.width, windowFrame.width, accuracy: 1, "横屏首帧仍在使用竖屏页面宽度")
// 横屏单页按宽度适配:cell 高度是纸张按全宽换算的实际高度,竖版纸张
// 高于一屏,纵向超出部分由阅读器连续竖滑承接,因此不再等于窗口高度。
XCTAssertGreaterThanOrEqual(
content.frame.height,
windowFrame.height - 1,
"横屏单页高度应不小于一屏(宽度适配后的纸张高度)"
)
}
func testFixedLayoutCachedPageCanReturnAfterPageTurn() {
app.launchAndOpenSampleBook(bookTitleQuery: "熊爷爷")
app.waitForReader()
let content = app.otherElements[IDs.readerContent]
XCTAssertTrue(content.waitForExistence(timeout: 5), "固定版式阅读区域未出现")
let initialState = app.waitForDemoReaderState(timeout: 5, description: "固定版式初始页") {
$0.page != nil
}
let initialPage = initialState.page ?? 0
content.swipeLeft()
let nextState = app.waitForDemoReaderState(timeout: 8, description: "固定版式向后翻页") { state in
guard let page = state.page else { return false }
return page != initialPage
}
content.swipeRight()
let returnedState = app.waitForDemoReaderState(timeout: 8, description: "固定版式返回缓存页") {
$0.page == initialPage
}
XCTAssertNotEqual(nextState.page, returnedState.page, "固定版式返回缓存页后页码未恢复")
XCTAssertTrue(content.exists, "返回缓存页后阅读区域不应消失")
}
}