17 Commits
Author SHA1 Message Date
shenlei 68d9363f0a feat: optimize reader caching and document formats 2026-07-20 17:22:06 +09:00
shenandshen 52f803e8db fix: restore demo build and drawing interactions 2026-07-15 21:13:05 +08:00
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
shenleiandClaude Fable 5 a17164d1a9 将 PDF 注释编辑器、笔记列表、目录/设置面板与面板呈现下沉到 SDK
SDK 新增:
- RDPDFReaderAnnotationEditorViewController:注释输入页(UI 与 EPUB 编辑器一致)
- RDPDFReaderAnnotationListViewController:笔记列表(全部/注释/高亮筛选、滑动删除)
- RDPDFReaderNavigationPanelViewController:目录/书签/缩略图面板容器
- RDPDFReaderSettingsPanelViewController:亮度/翻页方式/主题设置面板
- RDPDFReaderPanelPresenter + 转场/呈现控制器:底部面板统一呈现,
  转场代理生命周期由被呈现控制器持有,宿主无需保存引用
- RDPDFReaderThemeOption:SDK 自有主题模型,面板与编辑器不再依赖 EPUB 主题类型
- UIColor(rdPDFHexString:) 公开,并消除覆盖层内的私有重复实现

Demo 侧:
- 删除 PDFDemoAnnotationUI.swift 整个文件
- 删除 PDFDemoNavigationViewController / PDFDemoSettingsViewController /
  面板转场三个类(约 410 行),改为调用 SDK 组件
- ThemePreset 增加到 RDPDFReaderThemeOption 的映射

无障碍标识全部保留,UI 自动化不受影响。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 10:51:51 +09:00
shenleiandClaude Fable 5 1bde945d36 将 PDF 划线/注释交互完整下沉到 SDK 库
- RDPDFReaderPageView:完整页面视图移入 SDK(缩放画布、文字选择层、
  选区放大镜、无障碍视口),并内置与 EPUB 一致的两套系统编辑菜单:
  选区菜单(复制/划线/注释)、已有划线菜单(复制/注释|删除注释/删除划线)
- RDPDFReaderPageViewDelegate:宿主只通过代理做数据持久化与打开业务界面
- 修复划线命中判定:点击点先归一化再与标注比例坐标比较
- 修复 tappedHighlight 残留导致选区菜单项被错误过滤的问题
- 主题应用改为纯颜色入参,SDK 不依赖 EPUB 主题类型
- RDPDFReaderHighlightOverlayView 恢复为纯绘制层,点击交互统一由页面视图处理
- Demo 删除 PDFDemoPageView(约 290 行),改为实现代理回调

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 10:33:43 +09:00
shenleiandClaude Haiku 4.5 5a19cfde14 refactor: move highlight menu logic from Demo to SDK library
Add RDPDFReaderPageView as base page view class in SDK:
- Handles all highlight menu interactions and display
- Provides RDPDFReaderPageViewDelegate for menu action callbacks
- Unifies with EPUB architecture: RDEPUBTextContentView pattern
- Reduces code duplication for applications using the SDK

Benefits:
- Reusable menu interaction logic across all PDF apps
- Consistent architecture with EPUB reader
- Single responsibility principle (UI in library, persistence in app)
- Backward compatible (existing code continues to work)

Applications now implement RDPDFReaderPageViewDelegate to:
- Respond to highlight menu actions
- Handle data persistence
- Refresh UI after changes

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-15 10:19:54 +09:00
shenleiandClaude Haiku 4.5 7c16647306 fix: remove duplicate canPerformAction method and merge with existing implementation
- Keep single canPerformAction method that handles both text selection menu and highlight menu
- Check tappedHighlight first, then fall back to text selection logic
- Resolves method override conflict

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-15 10:16:30 +09:00
shenleiandClaude Haiku 4.5 d56e99a83f add tap-on-highlight menu with copy/annotate/delete actions, matching EPUB behavior
- Add RDPDFReaderAnnotationMenuAction and RDPDFReaderExistingHighlightMenuAction enums to PDF contracts
- Enable highlight overlay view to detect tap gestures and report tapped highlights
- Implement existing highlight menu in Demo page: copy text, add/edit annotation, delete annotation, delete underline
- Handle menu actions in PDFDemoReaderViewController to persist changes
- Ensure highlight tap detection doesn't interfere with text selection

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-15 10:06:02 +09:00
shenleiandClaude Haiku 4.5 fed34da246 unify PDF and EPUB reader: convert highlights to underlines, improve annotation UI, change paging from horizontal to vertical
- Convert PDF highlights from filled rectangles to underlines matching EPUB style
- Update PDF annotation editor with EPUB-style design: gold sidebar rail, semi-transparent background, improved spacing and shadows, dark mode support
- Change PDF page-curl paging from left-right horizontal to up-down vertical: update gesture recognition and tap regions accordingly

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-15 10:01:23 +09:00
shenlei 72c1f8d89c 扩展顶部工具栏业务按钮能力 2026-07-13 16:16:31 +09:00
shenlei 822949f6cc 清理重复 Podfile 配置 2026-07-13 16:09:45 +09:00
shenlei 6a0a1223b1 完善阅读器主题与批注界面 2026-07-13 13:01:14 +09:00
shenlei adc24d3f36 fix: preserve images in dark reader theme 2026-07-13 12:30:14 +09:00
shenandshen 8ccb7157b2 feat: improve epub reader controls and annotations 2026-07-12 12:23:10 +08:00
shenandshen 063a493b18 fix epub reader playback and trial navigation 2026-07-11 08:16:56 +08:00
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
shenleiandClaude Fable 5 d5a7755702 feat: 支持加密 EPUB、试读墙、工具栏定制与朝向锁定
- 新增 RDEPUBResourceDataProvider 解密钩子协议 + 访问登记表,收敛章节 HTML/
  图片/内联 CSS/脚注/封面/图片查看器/正文取图等读取点,scheme handler 对加密书
  禁用流式分支;新增 RDEPUBDecryptingImageAttachment 解密 DTCoreText 图片附件;
  RDEPUBReaderDependencies.live(resourceDataProvider:) 便捷注入。明文书零影响。
- 试读墙:configuration.trialPolicy + delegate epubReaderTrialWallView/
  DidReachTrialWall,UI 由宿主提供(RDEPUBReaderController+Trial)。
- 工具栏定制:RDEPUBReaderTop/BottomToolViewProtocol 协议 + dependencies 工厂注入,
  内置栏已 conform,configureTopToolView 改协议类型。
- 朝向锁定:RDEPUBMetadata.orientation(OPF rendition:orientation 主,
  iBooks display-options 兜底)+ RDEPUBReaderController+Orientation 重写支持朝向、
  打开后主动转向。

注:RDEPUBReaderController+LocationResolution / PaginationCoordinator 为本次改动前
即存在的工作区修改,一并纳入。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 12:25:17 +09:00
618 changed files with 20271 additions and 7423 deletions
+32
View File
@@ -6,3 +6,35 @@ xcuserdata/
.artifacts/ .artifacts/
.deriveddata/ .deriveddata/
.swift-module-cache/ .swift-module-cache/
ReadViewDemo/build/
# This repository checks in the Demo Pods project. Keep generated files for the
# local RDEpubReaderView/RDPDFReaderView pods and vendored SnapKit visible even
# when a global gitignore excludes Pods.
!ReadViewDemo/Pods/
!ReadViewDemo/Pods/Local Podspecs/
!ReadViewDemo/Pods/Local Podspecs/RDEpubReaderView.podspec.json
!ReadViewDemo/Pods/Local Podspecs/RDPDFReaderView.podspec.json
!ReadViewDemo/Pods/Target Support Files/
!ReadViewDemo/Pods/Target Support Files/RDEpubReaderView/
!ReadViewDemo/Pods/Target Support Files/RDEpubReaderView/**
!ReadViewDemo/Pods/Target Support Files/RDPDFReaderView/
!ReadViewDemo/Pods/Target Support Files/RDPDFReaderView/**
!ReadViewDemo/Pods/SnapKit/
!ReadViewDemo/Pods/SnapKit/**
!ReadViewDemo/Pods/Target Support Files/SnapKit/
!ReadViewDemo/Pods/Target Support Files/SnapKit/**
# macOS system files
.DS_Store
# Local backup directories
*手动解包备份*
# AI tool output
_ssoft-output/
.claude/
# Python bytecode
__pycache__/
*.py[cod]
+2 -2
View File
@@ -1,7 +1,7 @@
# ReadViewSDK 代码审查报告 # ReadViewSDK 代码审查报告
> 审查日期:2026-06-26 > 审查日期:2026-06-26
> 审查范围:Sources/RDReaderView 全部源码 > 审查范围:Sources/RDEpubReaderView 全部源码
> 审查方法:逐文件阅读 + 交叉验证 + 线程模型分析 > 审查方法:逐文件阅读 + 交叉验证 + 线程模型分析
--- ---
@@ -148,4 +148,4 @@ func currentTextPageSize() -> CGSize {
| 🟡 P2 | P2-2 | javaScriptStringLiteral 实现依赖隐式假设 | 可维护性 | | 🟡 P2 | P2-2 | javaScriptStringLiteral 实现依赖隐式假设 | 可维护性 |
| 🔵 P3 | P3-1 | 后台线程同步 hop 主线程获取布局信息 | 线程模型 | | 🔵 P3 | P3-1 | 后台线程同步 hop 主线程获取布局信息 | 线程模型 |
**整体评价**: SDK 架构设计良好,模块分层清晰,引用管理(unowned/weak)使用正确,分页取消机制有 `paginationToken` + `cancellationController` 兜底。主要值得修复的是三个性能类 P1 问题(主线程阻塞搜索、资源加载阻塞、缓存无清理),两个 P2 鲁棒性/可维护性问题,以及一个 P3 线程模型优化建议。 **整体评价**: SDK 架构设计良好,模块分层清晰,引用管理(unowned/weak)使用正确,分页取消机制有 `paginationToken` + `cancellationController` 兜底。主要值得修复的是三个性能类 P1 问题(主线程阻塞搜索、资源加载阻塞、缓存无清理),两个 P2 鲁棒性/可维护性问题,以及一个 P3 线程模型优化建议。
+27 -27
View File
@@ -8,7 +8,7 @@
## 1. RDEPUBReaderController — 入口控制器 ## 1. RDEPUBReaderController — 入口控制器
**文件**`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` 及扩展 **文件**`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderController.swift` 及扩展
### 1.1 初始化 ### 1.1 初始化
@@ -180,7 +180,7 @@ func nativeTextSemanticSummary() -> String?
## 2. RDEPUBReaderDelegate — 委托协议 ## 2. RDEPUBReaderDelegate — 委托协议
**文件**`Sources/RDReaderView/EPUBUI/RDEPUBReaderDelegate.swift` **文件**`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderDelegate.swift`
所有方法均有默认空实现,可按需实现。 所有方法均有默认空实现,可按需实现。
@@ -232,7 +232,7 @@ public protocol RDEPUBReaderDelegate: AnyObject {
## 3. RDEPUBReaderPersistence — 持久化协议 ## 3. RDEPUBReaderPersistence — 持久化协议
**文件**`Sources/RDReaderView/EPUBUI/RDEPUBReaderPersistence.swift` **文件**`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderPersistence.swift`
```swift ```swift
public protocol RDEPUBReaderPersistence: AnyObject { public protocol RDEPUBReaderPersistence: AnyObject {
@@ -264,7 +264,7 @@ public protocol RDEPUBReaderPersistence: AnyObject {
## 4. RDEPUBReaderConfiguration — 配置模型 ## 4. RDEPUBReaderConfiguration — 配置模型
**文件**`Sources/RDReaderView/EPUBUI/Settings/RDEPUBReaderConfiguration.swift` **文件**`Sources/RDEpubReaderView/EPUBUI/Settings/RDEPUBReaderConfiguration.swift`
| 属性 | 类型 | 默认值 | 说明 | | 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------| |------|------|--------|------|
@@ -273,7 +273,7 @@ public protocol RDEPUBReaderPersistence: AnyObject {
| `fontChoice` | `RDEPUBReaderFontChoice` | `.system` | 字体选择(system/serif/rounded/monospaced | | `fontChoice` | `RDEPUBReaderFontChoice` | `.system` | 字体选择(system/serif/rounded/monospaced |
| `numberOfColumns` | `Int` | `1` | 每页列数(1 或 2 | | `numberOfColumns` | `Int` | `1` | 每页列数(1 或 2 |
| `columnGap` | `CGFloat` | `20` | 列间距 | | `columnGap` | `CGFloat` | `20` | 列间距 |
| `displayType` | `RDReaderView.DisplayType` | `.pageCurl` | 翻页模式 | | `displayType` | `RDEpubReaderView.DisplayType` | `.pageCurl` | 翻页模式 |
| `landscapeDualPageEnabled` | `Bool` | `true` | 横屏双页 | | `landscapeDualPageEnabled` | `Bool` | `true` | 横屏双页 |
| `showsTableOfContents` | `Bool` | `true` | 显示目录 | | `showsTableOfContents` | `Bool` | `true` | 显示目录 |
| `allowsHighlights` | `Bool` | `true` | 允许高亮 | | `allowsHighlights` | `Bool` | `true` | 允许高亮 |
@@ -301,50 +301,50 @@ public protocol RDEPUBReaderPersistence: AnyObject {
## 5. 翻页容器协议 ## 5. 翻页容器协议
**文件**`Sources/RDReaderView/ReaderView/RDReaderViewProtocols.swift` **文件**`Sources/RDEpubReaderView/ReaderView/RDEpubReaderViewProtocols.swift`
### 5.1 RDReaderPageProvider(推荐) ### 5.1 RDEpubReaderPageProvider(推荐)
```swift ```swift
@objc public protocol RDReaderPageProvider: NSObjectProtocol { @objc public protocol RDEpubReaderPageProvider: NSObjectProtocol {
/// ///
func numberOfPages(in readerView: RDReaderView) -> Int func numberOfPages(in readerView: RDEpubReaderView) -> Int
/// ///
/// - Parameters: /// - Parameters:
/// - index: 0-based /// - index: 0-based
/// - reusableView: nil /// - reusableView: nil
func readerView(_ readerView: RDReaderView, viewForPageAt index: Int, reusableView: UIView?) -> UIView func readerView(_ readerView: RDEpubReaderView, viewForPageAt index: Int, reusableView: UIView?) -> UIView
/// ///
@objc optional func pageIdentifier(in readerView: RDReaderView, index: Int) -> String? @objc optional func pageIdentifier(in readerView: RDEpubReaderView, index: Int) -> String?
/// ///
@objc optional func readerViewTopChrome(_ readerView: RDReaderView) -> UIView? @objc optional func readerViewTopChrome(_ readerView: RDEpubReaderView) -> UIView?
/// ///
@objc optional func readerViewBottomChrome(_ readerView: RDReaderView) -> UIView? @objc optional func readerViewBottomChrome(_ readerView: RDEpubReaderView) -> UIView?
} }
``` ```
### 5.2 RDReaderDelegate ### 5.2 RDEpubReaderDelegate
```swift ```swift
@objc public protocol RDReaderDelegate: NSObjectProtocol { @objc public protocol RDEpubReaderDelegate: NSObjectProtocol {
/// ///
func pageNum(readerView: RDReaderView, pageNum: Int) func pageNum(readerView: RDEpubReaderView, pageNum: Int)
/// ///
@objc optional func readerViewOrientationWillChange(readerView: RDReaderView, isLandscape: Bool) @objc optional func readerViewOrientationWillChange(readerView: RDEpubReaderView, isLandscape: Bool)
} }
``` ```
### 5.3 RDReaderPageNavigating ### 5.3 RDEpubReaderPageNavigating
```swift ```swift
public protocol RDReaderPageNavigating: AnyObject { public protocol RDEpubReaderPageNavigating: AnyObject {
/// ///
var currentPage: Int { get } var currentPage: Int { get }
@@ -357,19 +357,19 @@ public protocol RDReaderPageNavigating: AnyObject {
} }
``` ```
### 5.4 RDReaderDataSource(遗留) ### 5.4 RDEpubReaderDataSource(遗留)
```swift ```swift
@objc public protocol RDReaderDataSource: NSObjectProtocol { @objc public protocol RDEpubReaderDataSource: NSObjectProtocol {
func pageCountOfReaderView(readerView: RDReaderView) -> Int func pageCountOfReaderView(readerView: RDEpubReaderView) -> Int
func pageContentView(readerView: RDReaderView, pageNum: Int, containerView: UIView?) -> UIView func pageContentView(readerView: RDEpubReaderView, pageNum: Int, containerView: UIView?) -> UIView
func pageIdentifier(readerView: RDReaderView, pageNum: Int) -> String? func pageIdentifier(readerView: RDEpubReaderView, pageNum: Int) -> String?
@objc optional func topToolView(readerView: RDReaderView) -> UIView? @objc optional func topToolView(readerView: RDEpubReaderView) -> UIView?
@objc optional func bottomToolView(readerView: RDReaderView) -> UIView? @objc optional func bottomToolView(readerView: RDEpubReaderView) -> UIView?
} }
``` ```
通过 `RDReaderLegacyDataSourceAdapter` 自动适配到 `RDReaderPageProvider` 通过 `RDEpubReaderLegacyDataSourceAdapter` 自动适配到 `RDEpubReaderPageProvider`
--- ---
+25 -25
View File
@@ -22,7 +22,7 @@ ReadViewSDK 是一个 iOS EPUB 阅读器 SDK,支持文本重排(Reflowable
│ ReadViewDemo (Demo App) │ │ ReadViewDemo (Demo App) │
│ ViewController · LaunchAutomationPlan · UITests │ │ ViewController · LaunchAutomationPlan · UITests │
└──────────────────────────────┬──────────────────────────────┘ └──────────────────────────────┬──────────────────────────────┘
│ imports RDReaderView │ imports RDEpubReaderView
┌──────────────────────────────▼──────────────────────────────┐ ┌──────────────────────────────▼──────────────────────────────┐
│ EPUBUI 层 │ │ EPUBUI 层 │
│ RDEPUBReaderController · Coordinators · Settings · TextPage │ │ RDEPUBReaderController · Coordinators · Settings · TextPage │
@@ -30,8 +30,8 @@ ReadViewSDK 是一个 iOS EPUB 阅读器 SDK,支持文本重排(Reflowable
└──────────────────────────────┬──────────────────────────────┘ └──────────────────────────────┬──────────────────────────────┘
┌──────────────────────────────▼──────────────────────────────┐ ┌──────────────────────────────▼──────────────────────────────┐
│ RDReaderView 层 │ │ RDEpubReaderView 层 │
│ RDReaderView · FlowLayout · PreloadController │ │ RDEpubReaderView · FlowLayout · PreloadController │
│ SpreadResolver · TapRegionHandler · PagingController │ │ SpreadResolver · TapRegionHandler · PagingController │
└──────────────────────────────┬──────────────────────────────┘ └──────────────────────────────┬──────────────────────────────┘
@@ -54,7 +54,7 @@ ReadViewSDK 是一个 iOS EPUB 阅读器 SDK,支持文本重排(Reflowable
|---|---|---| |---|---|---|
| **EPUBCore** | EPUB 文件解析、资源管理、WebView 渲染、JS 桥接 | `RDEPUBParser`, `RDEPUBPublication`, `RDEPUBWebView` | | **EPUBCore** | EPUB 文件解析、资源管理、WebView 渲染、JS 桥接 | `RDEPUBParser`, `RDEPUBPublication`, `RDEPUBWebView` |
| **EPUBTextRendering** | HTML→NSAttributedString 转换、排版、分页、全书构建 | `RDEPUBTextBookBuilder`, `RDEPUBCoreTextPageFrameFactory` | | **EPUBTextRendering** | HTML→NSAttributedString 转换、排版、分页、全书构建 | `RDEPUBTextBookBuilder`, `RDEPUBCoreTextPageFrameFactory` |
| **RDReaderView** | 通用翻页容器、手势识别、页面预加载、双页布局 | `RDReaderView`, `RDReaderFlowLayout`, `RDReaderPreloadController` | | **RDEpubReaderView** | 通用翻页容器、手势识别、页面预加载、双页布局 | `RDEpubReaderView`, `RDEpubReaderFlowLayout`, `RDEpubReaderPreloadController` |
| **EPUBUI** | 阅读器控制器、协调器模式、设置面板、按需加载、磁盘缓存 | `RDEPUBReaderController`, `RDEPUBReaderPaginationCoordinator` | | **EPUBUI** | 阅读器控制器、协调器模式、设置面板、按需加载、磁盘缓存 | `RDEPUBReaderController`, `RDEPUBReaderPaginationCoordinator` |
--- ---
@@ -310,10 +310,10 @@ RDEPUBWebView (UIView)
--- ---
## 7. 翻页容器架构(RDReaderView ## 7. 翻页容器架构(RDEpubReaderView
``` ```
RDReaderView (UIView) RDEpubReaderView (UIView)
├─ 三种翻页模式: ├─ 三种翻页模式:
│ ├─ .pageCurl → UIPageViewController (翻页动画) │ ├─ .pageCurl → UIPageViewController (翻页动画)
@@ -321,14 +321,14 @@ RDReaderView (UIView)
│ └─ .verticalScroll → UICollectionView (垂直滚动) │ └─ .verticalScroll → UICollectionView (垂直滚动)
├─ 组合对象: ├─ 组合对象:
│ ├─ RDReaderPagingController // 翻页状态管理、请求队列 │ ├─ RDEpubReaderPagingController // 翻页状态管理、请求队列
│ ├─ RDReaderPreloadController // 页面预加载、缓存管理 │ ├─ RDEpubReaderPreloadController // 页面预加载、缓存管理
│ ├─ RDReaderSpreadResolver // 双页展开计算 │ ├─ RDEpubReaderSpreadResolver // 双页展开计算
│ └─ RDReaderTapRegionHandler // 点击区域分类(左/中/右) │ └─ RDEpubReaderTapRegionHandler // 点击区域分类(左/中/右)
├─ 数据源协议: ├─ 数据源协议:
│ ├─ RDReaderPageProvider (新) // 格式无关,优先级高 │ ├─ RDEpubReaderPageProvider (新) // 格式无关,优先级高
│ └─ RDReaderDataSource (旧) // 遗留兼容,通过 Adapter 适配 │ └─ RDEpubReaderDataSource (旧) // 遗留兼容,通过 Adapter 适配
└─ 手势流: └─ 手势流:
点击 → TapRegionHandler → 分类(左/中/右) 点击 → TapRegionHandler → 分类(左/中/右)
@@ -351,7 +351,7 @@ struct RDEPUBReaderConfiguration {
var numberOfColumns: Int // 1 2 var numberOfColumns: Int // 1 2
var columnGap: CGFloat // 20 var columnGap: CGFloat // 20
var theme: ReaderTheme // 6 var theme: ReaderTheme // 6
var displayType: RDReaderView.DisplayType // pageCurl/horizontal/vertical var displayType: RDEpubReaderView.DisplayType // pageCurl/horizontal/vertical
var onDemandChapterWindowSize: Int // 3 3 15 var onDemandChapterWindowSize: Int // 3 3 15
var metadataParsingConcurrency: Int // CPU var metadataParsingConcurrency: Int // CPU
var chapterWindowRadius: Int // var chapterWindowRadius: Int //
@@ -374,7 +374,7 @@ struct RDEPUBReaderConfiguration {
## 9. 目录结构 ## 9. 目录结构
``` ```
Sources/RDReaderView/ Sources/RDEpubReaderView/
├── EPUBCore/ # EPUB 解析与 WebView 渲染 ├── EPUBCore/ # EPUB 解析与 WebView 渲染
│ ├── Models/ # 数据模型 │ ├── Models/ # 数据模型
│ │ ├── RDEPUBAnnotationModels.swift │ │ ├── RDEPUBAnnotationModels.swift
@@ -428,19 +428,19 @@ Sources/RDReaderView/
│ ├── RDEPUBDTCoreTextRenderer.swift # DTCoreText 渲染器实现 │ ├── RDEPUBDTCoreTextRenderer.swift # DTCoreText 渲染器实现
│ ├── RDEPUBChapterData.swift # 章节查询门面 │ ├── RDEPUBChapterData.swift # 章节查询门面
│ ├── RDEPUBTextIndexTable.swift # 全书索引表 │ ├── RDEPUBTextIndexTable.swift # 全书索引表
│ └── RDPlainTextBookBuilder.swift # 纯文本 (.txt) 构建器 │ └── RDEpubPlainTextBookBuilder.swift # 纯文本 (.txt) 构建器
├── ReaderView/ # 通用翻页容器 ├── ReaderView/ # 通用翻页容器
│ ├── Paging/ # 翻页子系统 │ ├── Paging/ # 翻页子系统
│ │ ├── RDReaderPagingController.swift │ │ ├── RDEpubReaderPagingController.swift
│ │ ├── RDReaderPreloadController.swift │ │ ├── RDEpubReaderPreloadController.swift
│ │ ├── RDReaderSpreadResolver.swift │ │ ├── RDEpubReaderSpreadResolver.swift
│ │ └── RDReaderTapRegionHandler.swift │ │ └── RDEpubReaderTapRegionHandler.swift
│ ├── RDReaderView.swift # 主容器视图 │ ├── RDEpubReaderView.swift # 主容器视图
│ ├── RDReaderView+*.swift # 扩展(CollectionView/PageCurl/ToolView/ContentAccess │ ├── RDEpubReaderView+*.swift # 扩展(CollectionView/PageCurl/ToolView/ContentAccess
│ ├── RDReaderFlowLayout.swift # 自定义 CollectionView 布局 │ ├── RDEpubReaderFlowLayout.swift # 自定义 CollectionView 布局
│ ├── RDReaderContentCell.swift # 滚动模式 Cell │ ├── RDEpubReaderContentCell.swift # 滚动模式 Cell
│ └── RDReaderPageChildViewController.swift // 翻页模式子 VC │ └── RDEpubReaderPageChildViewController.swift // 翻页模式子 VC
└── EPUBUI/ # 阅读器 UI └── EPUBUI/ # 阅读器 UI
├── ReaderController/ # 控制器与协调器 ├── ReaderController/ # 控制器与协调器
@@ -494,7 +494,7 @@ Sources/RDReaderView/
| **Builder** | `RDEPUBBookPageMap.Builder` 增量构建页码映射 | | **Builder** | `RDEPUBBookPageMap.Builder` 增量构建页码映射 |
| **Strategy** | `RDEPUBTextRenderer` 协议,可替换渲染器实现 | | **Strategy** | `RDEPUBTextRenderer` 协议,可替换渲染器实现 |
| **Pipeline** | `RDEPUBTextTypesetterPipeline` 排版管线(8 个逻辑阶段,封装为 5-6 个顶层调用) | | **Pipeline** | `RDEPUBTextTypesetterPipeline` 排版管线(8 个逻辑阶段,封装为 5-6 个顶层调用) |
| **Adapter** | `RDReaderLegacyDataSourceAdapter` 适配旧数据源协议 | | **Adapter** | `RDEpubReaderLegacyDataSourceAdapter` 适配旧数据源协议 |
| **三级缓存** | 内存 → 磁盘摘要 → 全书分页,逐级降级 | | **三级缓存** | 内存 → 磁盘摘要 → 全书分页,逐级降级 |
| **Token 取消** | `paginationToken` 确保过期异步任务不干扰新任务 | | **Token 取消** | `paginationToken` 确保过期异步任务不干扰新任务 |
| **Frozen Parameters** | 后台任务冻结 `renderSignature`,避免运行中参数漂移 | | **Frozen Parameters** | 后台任务冻结 `renderSignature`,避免运行中参数漂移 |
+3 -3
View File
@@ -1,6 +1,6 @@
# ReadViewSDK 代码审查报告 # ReadViewSDK 代码审查报告
> 审查范围:`Sources/RDReaderView/` 全部 184 个 Swift 文件(约 32,300 行) > 审查范围:`Sources/RDEpubReaderView/` 全部 184 个 Swift 文件(约 32,300 行)
> 审查维度:并发安全、内存管理、API 正确性、Swift/iOS 平台特定、架构与依赖 > 审查维度:并发安全、内存管理、API 正确性、Swift/iOS 平台特定、架构与依赖
> 审查日期:2026-06-26 > 审查日期:2026-06-26
@@ -134,7 +134,7 @@ let stillChanged = abs(currentSize.width - self.lastTextPaginationPageSize!.widt
### H-10 · 依赖版本未锁定 ### H-10 · 依赖版本未锁定
`RDReaderView.podspec` 中 DTCoreText、SnapKit、SSAlertSwift 无版本约束: `RDEpubReaderView.podspec` 中 DTCoreText、SnapKit、SSAlertSwift 无版本约束:
```ruby ```ruby
s.dependency 'ZIPFoundation', '~> 0.9' # ✅ 已锁定 s.dependency 'ZIPFoundation', '~> 0.9' # ✅ 已锁定
@@ -143,7 +143,7 @@ s.dependency 'SnapKit' # ❌ 无约束
s.dependency 'SSAlertSwift' # ❌ 无约束 s.dependency 'SSAlertSwift' # ❌ 无约束
``` ```
**位置:** `RDReaderView.podspec:17-20` **位置:** `RDEpubReaderView.podspec:17-20`
--- ---
+4 -4
View File
@@ -298,14 +298,14 @@ return builder.build()
**触发条件:** `landscapeDualPageEnabled && isLandscape && !verticalScroll` **触发条件:** `landscapeDualPageEnabled && isLandscape && !verticalScroll`
**页面配对逻辑(RDReaderSpreadResolver):** **页面配对逻辑(RDEpubReaderSpreadResolver):**
- 有封面页:封面独占一屏,后续页面两两配对 - 有封面页:封面独占一屏,后续页面两两配对
- 配对规则:`(coverIndex, nil)`, `(1, 2)`, `(3, 4)`, ... - 配对规则:`(coverIndex, nil)`, `(1, 2)`, `(3, 4)`, ...
- 无封面页:标准偶奇配对 - 无封面页:标准偶奇配对
- 配对规则:`(0, 1)`, `(2, 3)`, `(4, 5)`, ... - 配对规则:`(0, 1)`, `(2, 3)`, `(4, 5)`, ...
**封面感知布局(RDReaderFlowLayout):** **封面感知布局(RDEpubReaderFlowLayout):**
``` ```
封面页: [====全屏宽度====] 封面页: [====全屏宽度====]
@@ -314,7 +314,7 @@ return builder.build()
### 5.3 页面预加载 ### 5.3 页面预加载
`RDReaderPreloadController` 管理两个缓存: `RDEpubReaderPreloadController` 管理两个缓存:
- `preloadedPageViews` - 预渲染的页面视图 - `preloadedPageViews` - 预渲染的页面视图
- `pageCurlCachedViews` - 当前显示的页面视图 - `pageCurlCachedViews` - 当前显示的页面视图
@@ -580,7 +580,7 @@ protocol RDEPUBReaderPersistence {
## 9. 纯文本 (.txt) 支持 ## 9. 纯文本 (.txt) 支持
`RDPlainTextBookBuilder` 复用 EPUB 渲染管线处理 .txt 文件: `RDEpubPlainTextBookBuilder` 复用 EPUB 渲染管线处理 .txt 文件:
1. **解码:** 依次尝试 UTF-8 → GB18030 → GBK 1. **解码:** 依次尝试 UTF-8 → GB18030 → GBK
2. **分章:** 正则匹配 `^(第[零一二三四五六七八九十百千万\d]+[章节回卷].*)$` 2. **分章:** 正则匹配 `^(第[零一二三四五六七八九十百千万\d]+[章节回卷].*)$`
+13 -13
View File
@@ -34,7 +34,7 @@ epubcfi(/6/4!ch01.xhtml/4/2/1:3)
顶层 CFI 模型,对应一个完整的 `epubcfi(...)` 字符串。 顶层 CFI 模型,对应一个完整的 `epubcfi(...)` 字符串。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFI.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFI.swift`
```swift ```swift
public struct RDEPUBCFI: Codable, Equatable, Hashable { public struct RDEPUBCFI: Codable, Equatable, Hashable {
@@ -66,7 +66,7 @@ public enum RDEPUBCFISideBias: String, Codable {
路径模型,由一组 `RDEPUBCFIStep` 组成,描述从根节点到目标节点的遍历序列。 路径模型,由一组 `RDEPUBCFIStep` 组成,描述从根节点到目标节点的遍历序列。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIPath.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIPath.swift`
```swift ```swift
public struct RDEPUBCFIPath: Codable, Equatable, Hashable { public struct RDEPUBCFIPath: Codable, Equatable, Hashable {
@@ -95,7 +95,7 @@ public struct RDEPUBCFIStep: Codable, Equatable, Hashable {
范围模型,表示文档中的一个连续区域,由父级 CFI 和起止 CFI 组成。 范围模型,表示文档中的一个连续区域,由父级 CFI 和起止 CFI 组成。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIRange.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIRange.swift`
```swift ```swift
public struct RDEPUBCFIRange: Codable, Equatable, Hashable { public struct RDEPUBCFIRange: Codable, Equatable, Hashable {
@@ -116,7 +116,7 @@ public struct RDEPUBCFIRange: Codable, Equatable, Hashable {
将 CFI 字符串解析为结构化模型。 将 CFI 字符串解析为结构化模型。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIParser.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIParser.swift`
```swift ```swift
public enum RDEPUBCFIParser { public enum RDEPUBCFIParser {
@@ -154,7 +154,7 @@ print(cfi.textAssertion?.exact) // Optional("目标文本")
将 CFI 模型序列化为标准字符串。 将 CFI 模型序列化为标准字符串。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFISerializer.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFISerializer.swift`
```swift ```swift
public enum RDEPUBCFISerializer { public enum RDEPUBCFISerializer {
@@ -192,7 +192,7 @@ let serialized = RDEPUBCFISerializer.serialize(cfi)
将 CFI 解析为可直接用于资源定位的结果。 将 CFI 解析为可直接用于资源定位的结果。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIResolver.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIResolver.swift`
```swift ```swift
public struct RDEPUBCFIResolverResult: Equatable { public struct RDEPUBCFIResolverResult: Equatable {
@@ -228,7 +228,7 @@ print(result.chapterOffset) // Optional(80)
从已知的章节信息生成 CFI。 从已知的章节信息生成 CFI。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIGenerator.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIGenerator.swift`
```swift ```swift
public enum RDEPUBCFIGenerator { public enum RDEPUBCFIGenerator {
@@ -274,7 +274,7 @@ public enum RDEPUBCFIGenerator {
从 HTML 源码中提取带有 `id` 属性的元素路径映射。 从 HTML 源码中提取带有 `id` 属性的元素路径映射。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIDOMPathBuilder.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIDOMPathBuilder.swift`
```swift ```swift
public enum RDEPUBCFIDOMPathBuilder { public enum RDEPUBCFIDOMPathBuilder {
@@ -296,7 +296,7 @@ public enum RDEPUBCFIDOMPathBuilder {
当 CFI 精确定位失败时(如 DOM 结构变更),恢复引擎通过多级降级策略尝试找到最佳匹配位置。 当 CFI 精确定位失败时(如 DOM 结构变更),恢复引擎通过多级降级策略尝试找到最佳匹配位置。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIRecoveryEngine.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIRecoveryEngine.swift`
### 5.1 恢复置信度 ### 5.1 恢复置信度
@@ -361,7 +361,7 @@ let result = RDEPUBCFIRecoveryEngine.recover(
文本断言用于在 CFI 定位后验证所指位置的文本内容是否符合预期,增强定位鲁棒性。 文本断言用于在 CFI 定位后验证所指位置的文本内容是否符合预期,增强定位鲁棒性。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFITextAssertion.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFITextAssertion.swift`
```swift ```swift
public struct RDEPUBCFITextAssertion: Codable, Equatable, Hashable { public struct RDEPUBCFITextAssertion: Codable, Equatable, Hashable {
@@ -393,7 +393,7 @@ print(assertion?.suffix) // Optional("后续内容")
提供宽松解析接口,兼容非标准 CFI 格式。 提供宽松解析接口,兼容非标准 CFI 格式。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFICompatibility.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFICompatibility.swift`
```swift ```swift
public enum RDEPUBCFICompatibility { public enum RDEPUBCFICompatibility {
@@ -418,7 +418,7 @@ public enum RDEPUBCFICompatibility {
CFI 映射是章节级别的索引结构,将 CFI 路径映射到章节文本偏移量,是容错恢复引擎的核心数据源。 CFI 映射是章节级别的索引结构,将 CFI 路径映射到章节文本偏移量,是容错恢复引擎的核心数据源。
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIMap.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIMap.swift`
### 8.1 RDEPUBCFIMap ### 8.1 RDEPUBCFIMap
@@ -506,7 +506,7 @@ public struct RDEPUBCFITokenAnchor: Codable, Equatable {
## 9. 错误类型(RDEPUBCFIError ## 9. 错误类型(RDEPUBCFIError
**文件**`Sources/RDReaderView/EPUBCore/CFI/RDEPUBCFIError.swift` **文件**`Sources/RDEpubReaderView/EPUBCore/CFI/RDEPUBCFIError.swift`
```swift ```swift
public enum RDEPUBCFIError: Error, Equatable { public enum RDEPUBCFIError: Error, Equatable {
+2 -2
View File
@@ -16,8 +16,8 @@
- 渐进补全:后台逐步补全所有章节的页码信息 - 渐进补全:后台逐步补全所有章节的页码信息
**关键文件** **关键文件**
- `Sources/RDReaderView/EPUBUI/ReaderController/ChapterRuntime/` 目录 - `Sources/RDEpubReaderView/EPUBUI/ReaderController/ChapterRuntime/` 目录
- `Sources/RDReaderView/EPUBUI/ReaderController/RDEPUBReaderPaginationCoordinator.swift` - `Sources/RDEpubReaderView/EPUBUI/ReaderController/RDEPUBReaderPaginationCoordinator.swift`
--- ---
+9 -9
View File
@@ -105,15 +105,15 @@
## Evidence(仓库路径) ## Evidence(仓库路径)
- Build flags`Podfile` - Build flags`Podfile`
- Pod metadata/toolchain`RDReaderView.podspec` - Pod metadata/toolchain`RDEpubReaderView.podspec`
- Archive extraction`Sources/RDReaderView/EPUBCore/RDEPUBParser+Archive.swift` - Archive extraction`Sources/RDEpubReaderView/EPUBCore/RDEPUBParser+Archive.swift`
- Resource path validationpost-extraction):`Sources/RDReaderView/EPUBCore/RDEPUBParser+Resources.swift` - Resource path validationpost-extraction):`Sources/RDEpubReaderView/EPUBCore/RDEPUBParser+Resources.swift`
- Scheme handler reads full file bytes`Sources/RDReaderView/EPUBCore/RDEPUBResourceURLSchemeHandler.swift` - Scheme handler reads full file bytes`Sources/RDEpubReaderView/EPUBCore/RDEPUBResourceURLSchemeHandler.swift`
- WebView bridge + message handling`Sources/RDReaderView/EPUBCore/RDEPUBWebView+JavaScriptBridge.swift` - WebView bridge + message handling`Sources/RDEpubReaderView/EPUBCore/RDEPUBWebView+JavaScriptBridge.swift`
- External link opening`Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` - External link opening`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderController.swift`
- UserDefaults persistence implementation`Sources/RDReaderView/EPUBUI/RDEPUBReaderPersistence.swift` - UserDefaults persistence implementation`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderPersistence.swift`
- Hidden paginator web view`Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift` - Hidden paginator web view`Sources/RDEpubReaderView/EPUBCore/RDEPUBPaginator.swift`
- Debug logging`Sources/RDReaderView/EPUBCore/RDEPUBWebViewDebug.swift` - Debug logging`Sources/RDEpubReaderView/EPUBCore/RDEPUBWebViewDebug.swift`
- Vendored dependencies`Pods/``ReadViewDemo/Pods/` - Vendored dependencies`Pods/``ReadViewDemo/Pods/`
--- ---
+23 -23
View File
@@ -6,43 +6,43 @@
## 语言与工程约束 ## 语言与工程约束
- **主要语言**SwiftPodspec 声明 `s.swift_versions = ["5.10"]`,见 `RDReaderView.podspec` - **主要语言**SwiftPodspec 声明 `s.swift_versions = ["5.10"]`,见 `RDEpubReaderView.podspec`
- **最低系统版本**Podspec `iOS 15.0``RDReaderView.podspec`),示例工程 Podfile/构建设置里常见为 `iOS 15.6``Podfile` - **最低系统版本**Podspec `iOS 15.0``RDEpubReaderView.podspec`),示例工程 Podfile/构建设置里常见为 `iOS 15.6``ReadViewDemo/Podfile`
- **依赖管理**CocoaPods`Podfile``ReadViewDemo/Podfile``Podfile.lock` - **依赖管理**CocoaPods`ReadViewDemo/Podfile``ReadViewDemo/Podfile.lock`
## 命名约定 ## 命名约定
**文件/类型命名(Swift):** **文件/类型命名(Swift):**
- 以类型名为文件名的单文件组织较常见:`Sources/RDReaderView/EPUBCore/RDEPUBParser.swift` - 以类型名为文件名的单文件组织较常见:`Sources/RDEpubReaderView/EPUBCore/RDEPUBParser.swift`
- 大量使用前缀区分模块域: - 大量使用前缀区分模块域:
- `RD...`:阅读器 UI/控制器相关(如 `Sources/RDReaderView/RDReaderView.swift``Sources/RDReaderView/RDURLReaderController.swift` - `RD...`:阅读器 UI/控制器相关(如 `Sources/RDEpubReaderView/RDEpubReaderView.swift``Sources/RDEpubReaderView/RDEpubURLReaderController.swift`
- `RDEPUB...`EPUB Core/UI/渲染相关(如 `Sources/RDReaderView/EPUBCore/RDEPUBModels.swift` - `RDEPUB...`EPUB Core/UI/渲染相关(如 `Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift`
- Extension 文件使用 `+` 命名:`Sources/RDReaderView/EPUBUI/RDEPUBReaderController+ContentDelegates.swift` - Extension 文件使用 `+` 命名:`Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderController+ContentDelegates.swift`
**变量/函数命名:** **变量/函数命名:**
- 基本遵循 Swift lowerCamelCase`parse(epubURL:)``Sources/RDReaderView/EPUBCore/RDEPUBParser.swift` - 基本遵循 Swift lowerCamelCase`parse(epubURL:)``Sources/RDEpubReaderView/EPUBCore/RDEPUBParser.swift`
- 常量多用 `static let``kRDEPUBHighlightAttributeName``Sources/RDReaderView/EPUBCore/Models/RDEPUBAnnotationModels.swift` - 常量多用 `static let``kRDEPUBHighlightAttributeName``Sources/RDEpubReaderView/EPUBCore/Models/RDEPUBAnnotationModels.swift`
## 代码风格与排版(从现有代码归纳) ## 代码风格与排版(从现有代码归纳)
**缩进与换行:** **缩进与换行:**
- 多数文件使用 4 空格缩进(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift``Sources/RDReaderView/EPUBCore/RDEPUBModels.swift` - 多数文件使用 4 空格缩进(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift``Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift`
- 历史代码中更常见”强制换行/多行括号”风格 - 历史代码中更常见”强制换行/多行括号”风格
**空行与分组:** **空行与分组:**
- UI 相关文件常用空行分隔属性/初始化/布局段落 - UI 相关文件常用空行分隔属性/初始化/布局段落
- `// MARK:` 用于分区组织(示例:`Sources/RDReaderView/RDReaderGestureController.swift``Sources/RDReaderView/EPUBTextRendering/RDPlainTextBookBuilder.swift` - `// MARK:` 用于分区组织(示例:`Sources/RDEpubReaderView/RDEpubReaderGestureController.swift``Sources/RDEpubReaderView/EPUBTextRendering/RDEpubPlainTextBookBuilder.swift`
**类型组织:** **类型组织:**
- 偏好用 `extension` 拆分职责/协议实现(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift``UITableViewDataSource/Delegate` - 偏好用 `extension` 拆分职责/协议实现(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift``UITableViewDataSource/Delegate`
- API 暴露处使用 `public``public final class``public enum/struct`(示例:`Sources/RDReaderView/EPUBCore/RDEPUBModels.swift` - API 暴露处使用 `public``public final class``public enum/struct`(示例:`Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift`
- “对外只读、内部可写”常用 `public internal(set)`(示例:`Sources/RDReaderView/EPUBCore/RDEPUBParser.swift` - “对外只读、内部可写”常用 `public internal(set)`(示例:`Sources/RDEpubReaderView/EPUBCore/RDEPUBParser.swift`
## 导入与依赖使用 ## 导入与依赖使用
**import** **import**
- UIKit/UI 文件:`import UIKit`(大量文件) - UIKit/UI 文件:`import UIKit`(大量文件)
- Core/模型文件:`import Foundation`(如 `Sources/RDReaderView/EPUBCore/RDEPUBModels.swift` - Core/模型文件:`import Foundation`(如 `Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift`
- 三方依赖按需引入: - 三方依赖按需引入:
- `SnapKit`:布局 - `SnapKit`:布局
- `SSAlertSwift`:弹窗/提示 - `SSAlertSwift`:弹窗/提示
@@ -52,15 +52,15 @@
## 错误处理与日志 ## 错误处理与日志
- Core 解析层倾向用 `throws` + 自定义 `Error`(示例:`Sources/RDReaderView/EPUBCore/RDEPUBParser.swift``Sources/RDReaderView/EPUBCore/RDEPUBModels.swift``RDEPUBParserError` - Core 解析层倾向用 `throws` + 自定义 `Error`(示例:`Sources/RDEpubReaderView/EPUBCore/RDEPUBParser.swift``Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift``RDEPUBParserError`
- UI/控制器层常见 `guard` 早返回(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift` - UI/控制器层常见 `guard` 早返回(示例:`ReadViewDemo/ReadViewDemo/ViewController.swift`
- 未检测到统一日志框架(未发现专用 logging package/config);出现时以系统 API/局部输出为主(需按具体文件核对)。 - 未检测到统一日志框架(未发现专用 logging package/config);出现时以系统 API/局部输出为主(需按具体文件核对)。
## 注释与文档 ## 注释与文档
- **项目规则(强约束)**:代码标识符保持英文,但**代码注释/文档/提交信息使用中文**(见 `CONTEXT.md`)。 - **项目规则(强约束)**:代码标识符保持英文,但**代码注释/文档/提交信息使用中文**(见 `CONTEXT.md`)。
- 历史文件常带 Xcode 头部注释块(示例:`Sources/RDReaderView/ReaderView/RDReaderView.swift`)。 - 历史文件常带 Xcode 头部注释块(示例:`Sources/RDEpubReaderView/ReaderView/RDEpubReaderView.swift`)。
- 公共 API 处存在少量三斜线文档注释(示例:`Sources/RDReaderView/RDReaderView.swift` 的中文说明)。 - 公共 API 处存在少量三斜线文档注释(示例:`Sources/RDEpubReaderView/RDEpubReaderView.swift` 的中文说明)。
## Lint / Formatter / 静态检查 ## Lint / Formatter / 静态检查
@@ -76,10 +76,10 @@
## Evidence(关键证据文件) ## Evidence(关键证据文件)
- `CONTEXT.md` - `CONTEXT.md`
- `Podfile` - `ReadViewDemo/Podfile`
- `RDReaderView.podspec` - `RDEpubReaderView.podspec`
- `ReadViewDemo/ReadViewDemo/ViewController.swift` - `ReadViewDemo/ReadViewDemo/ViewController.swift`
- `Sources/RDReaderView/ReaderView/RDReaderView.swift` - `Sources/RDEpubReaderView/ReaderView/RDEpubReaderView.swift`
- `Sources/RDReaderView/EPUBCore/RDEPUBParser.swift` - `Sources/RDEpubReaderView/EPUBCore/RDEPUBParser.swift`
- `Sources/RDReaderView/EPUBCore/RDEPUBModels.swift` - `Sources/RDEpubReaderView/EPUBCore/RDEPUBModels.swift`
- `Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift` - `Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderController.swift`
+1 -1
View File
@@ -471,7 +471,7 @@ final class RDEPUBTextSearchEngine: RDEPUBSearchEngine {
## 9. 纯文本构建器 ## 9. 纯文本构建器
**文件:** `RDPlainTextBookBuilder.swift` **文件:** `RDEpubPlainTextBookBuilder.swift`
从纯文本(.txt)文件构建 `RDEPUBTextBook`,用于支持 TXT 格式阅读。 从纯文本(.txt)文件构建 `RDEPUBTextBook`,用于支持 TXT 格式阅读。
+8 -8
View File
@@ -48,7 +48,7 @@ public final class RDEPUBReaderController: UIViewController {
let epubURL: URL // EPUB let epubURL: URL // EPUB
let persistence: RDEPUBReaderPersistence? // let persistence: RDEPUBReaderPersistence? //
let dependencies: RDEPUBReaderDependencies // let dependencies: RDEPUBReaderDependencies //
let readerView = RDReaderView() // let readerView = RDEpubReaderView() //
} }
``` ```
@@ -57,7 +57,7 @@ public final class RDEPUBReaderController: UIViewController {
| 文件 | 职责 | | 文件 | 职责 |
|------|------| |------|------|
| `RDEPUBReaderController+PublicAPI.swift` | 公开 API(跳转、搜索、标注、书签) | | `RDEPUBReaderController+PublicAPI.swift` | 公开 API(跳转、搜索、标注、书签) |
| `RDEPUBReaderController+DataSource.swift` | `RDReaderPageProvider` 实现 | | `RDEPUBReaderController+DataSource.swift` | `RDEpubReaderPageProvider` 实现 |
| `RDEPUBReaderController+ContentDelegates.swift` | WebView/TextContentView 代理路由 | | `RDEPUBReaderController+ContentDelegates.swift` | WebView/TextContentView 代理路由 |
| `RDEPUBReaderController+LocationResolution.swift` | 页码/位置解析、阅读状态同步 | | `RDEPUBReaderController+LocationResolution.swift` | 页码/位置解析、阅读状态同步 |
| `RDEPUBReaderController+ExternalLinks.swift` | 外部链接处理(白名单、确认弹窗) | | `RDEPUBReaderController+ExternalLinks.swift` | 外部链接处理(白名单、确认弹窗) |
@@ -120,7 +120,7 @@ public protocol RDEPUBReaderPersistence: AnyObject {
```swift ```swift
final class RDEPUBReaderContext { final class RDEPUBReaderContext {
weak var controller: RDEPUBReaderController? weak var controller: RDEPUBReaderController?
weak var readerView: RDReaderView? weak var readerView: RDEpubReaderView?
var dependencies: RDEPUBReaderDependencies var dependencies: RDEPUBReaderDependencies
var runtime: RDEPUBReaderRuntime? var runtime: RDEPUBReaderRuntime?
@@ -155,7 +155,7 @@ public struct RDEPUBReaderDependencies {
public var makeParser: () -> RDEPUBParser public var makeParser: () -> RDEPUBParser
public var makePaginator: () -> RDEPUBPaginator public var makePaginator: () -> RDEPUBPaginator
public var makeTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextBookCache?, RDEPUBTextLayoutConfig) -> RDEPUBTextBookBuilder public var makeTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextBookCache?, RDEPUBTextLayoutConfig) -> RDEPUBTextBookBuilder
public var makePlainTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextLayoutConfig) -> RDPlainTextBookBuilder public var makePlainTextBookBuilder: (RDEPUBTextRenderer, RDEPUBTextLayoutConfig) -> RDEpubPlainTextBookBuilder
public var makeTextRenderer: (RDEPUBTextRenderingEngine) -> RDEPUBTextRenderer public var makeTextRenderer: (RDEPUBTextRenderingEngine) -> RDEPUBTextRenderer
public static var live: RDEPUBReaderDependencies // public static var live: RDEPUBReaderDependencies //
@@ -659,9 +659,9 @@ struct RDEPUBReaderUIState {
页图协调器(按需分页与全量分页的结果合并)。 页图协调器(按需分页与全量分页的结果合并)。
### 10.6 RDURLReaderController ### 10.6 RDEpubURLReaderController
**文件:** `RDURLReaderController.swift` **文件:** `RDEpubURLReaderController.swift`
URL 阅读器控制器(用于打开单个 URL)。 URL 阅读器控制器(用于打开单个 URL)。
@@ -715,12 +715,12 @@ RDEPUBReaderRuntime.applyParsedPublication()
├── RDEPUBBookPageMap 生成 ├── RDEPUBBookPageMap 生成
└── RDReaderView.transitionToPage() → 显示页面 └── RDEpubReaderView.transitionToPage() → 显示页面
用户翻页 用户翻页
RDReaderView.currentPage 变化 RDEpubReaderView.currentPage 变化
├── RDEPUBReaderLocationCoordinator.recordPageChangeIfNeeded() ├── RDEPUBReaderLocationCoordinator.recordPageChangeIfNeeded()
│ └── persistence.saveLocation() │ └── persistence.saveLocation()
+6 -6
View File
@@ -14,9 +14,9 @@
生成点: 生成点:
- `Sources/RDReaderView/EPUBUI/ReaderController/ChapterRuntime/RDEPUBChapterLoader.swift:494``buildPagesFromRanges` - `Sources/RDEpubReaderView/EPUBUI/ReaderController/ChapterRuntime/RDEPUBChapterLoader.swift:494``buildPagesFromRanges`
- `Sources/RDReaderView/EPUBTextRendering/BuildPipeline/RDEPUBTextBookBuilder.swift:294` - `Sources/RDEpubReaderView/EPUBTextRendering/BuildPipeline/RDEPUBTextBookBuilder.swift:294`
- `Sources/RDReaderView/EPUBTextRendering/RDPlainTextBookBuilder.swift:78` - `Sources/RDEpubReaderView/EPUBTextRendering/RDEpubPlainTextBookBuilder.swift:78`
现存全部消费点(已盘点确认,仅 3 处): 现存全部消费点(已盘点确认,仅 3 处):
@@ -27,7 +27,7 @@
**任务** **任务**
- [x]`RDEPUBTextPage.content` 改为按需构造:已改为基于 `chapterContent` + `contentRange` 的计算属性(带范围钳制),公开读取 API 不变 - [x]`RDEPUBTextPage.content` 改为按需构造:已改为基于 `chapterContent` + `contentRange` 的计算属性(带范围钳制),公开读取 API 不变
- [x] 三个构造点(`RDEPUBChapterLoader` / `RDEPUBTextBookBuilder` / `RDPlainTextBookBuilder`)不再生成每页子串;消费点经计算属性透明按需构造 - [x] 三个构造点(`RDEPUBChapterLoader` / `RDEPUBTextBookBuilder` / `RDEpubPlainTextBookBuilder`)不再生成每页子串;消费点经计算属性透明按需构造
- [x] `Equatable` 确认:`content` 为派生值,由 `contentRange` + `chapterContent` 判等覆盖,语义不变 - [x] `Equatable` 确认:`content` 为派生值,由 `contentRange` + `chapterContent` 判等覆盖,语义不变
**API 兼容性注意** **API 兼容性注意**
@@ -47,7 +47,7 @@
### P0-3 保持现有缓存限制,防止错误复用 ### P0-3 保持现有缓存限制,防止错误复用
- [x] `shouldAvoidReaderPageCaching``RDEPUBTextContentView.swift:319`)保持现状,已补注释说明放开的前置条件是 P1-1 落地 - [x] `shouldAvoidReaderPageCaching``RDEPUBTextContentView.swift:319`)保持现状,已补注释说明放开的前置条件是 P1-1 落地
- [x] 本阶段未改 `RDReaderPreloadController` 行为 - [x] 本阶段未改 `RDEpubReaderPreloadController` 行为
--- ---
@@ -101,7 +101,7 @@
前置:P1-1~P1-3 全部落地后,页面视图不再持有整章副本。 前置:P1-1~P1-3 全部落地后,页面视图不再持有整章副本。
- [ ] 调整 `shouldAvoidReaderPageCaching` 判定,允许轻量化后的文本页进入 `RDReaderPreloadController` 缓存 - [ ] 调整 `shouldAvoidReaderPageCaching` 判定,允许轻量化后的文本页进入 `RDEpubReaderPreloadController` 缓存
- [ ] 对比放开前后的翻页流畅度与峰值内存,数据不佳则回退此项 - [ ] 对比放开前后的翻页流畅度与峰值内存,数据不佳则回退此项
--- ---
+92 -92
View File
@@ -6,54 +6,54 @@
## 1. 模块概述 ## 1. 模块概述
`ReaderView` 是 ReadViewSDK 的**通用翻页容器层**,位于 EPUBUI 层之下。它提供与 EPUB 内容无关的页面展示、翻页动画、手势识别、页面预加载和双页布局能力。上层通过 `RDReaderPageProvider` 协议提供页面内容视图,ReaderView 负责容器管理和翻页调度。 `ReaderView` 是 ReadViewSDK 的**通用翻页容器层**,位于 EPUBUI 层之下。它提供与 EPUB 内容无关的页面展示、翻页动画、手势识别、页面预加载和双页布局能力。上层通过 `RDEpubReaderPageProvider` 协议提供页面内容视图,ReaderView 负责容器管理和翻页调度。
**文件清单(14 个 Swift 文件):** **文件清单(14 个 Swift 文件):**
| 文件 | 核心类型 | 职责 | | 文件 | 核心类型 | 职责 |
|------|----------|------| |------|----------|------|
| `RDReaderView.swift` | `RDReaderView` | 主容器视图,协调所有子组件 | | `RDEpubReaderView.swift` | `RDEpubReaderView` | 主容器视图,协调所有子组件 |
| `RDReaderViewProtocols.swift` | 协议 + 枚举 | 数据源、代理、导航协议定义 | | `RDEpubReaderViewProtocols.swift` | 协议 + 枚举 | 数据源、代理、导航协议定义 |
| `RDReaderFlowLayout.swift` | `RDReaderFlowLayout` | UICollectionView 自定义布局 | | `RDEpubReaderFlowLayout.swift` | `RDEpubReaderFlowLayout` | UICollectionView 自定义布局 |
| `RDReaderGestureController.swift` | `RDReaderGestureController` | 手势控制器(预留) | | `RDEpubReaderGestureController.swift` | `RDEpubReaderGestureController` | 手势控制器(预留) |
| `RDReaderContentCell.swift` | `RDReaderContentCell` | CollectionView 内容 Cell | | `RDEpubReaderContentCell.swift` | `RDEpubReaderContentCell` | CollectionView 内容 Cell |
| `RDReaderPageChildViewController.swift` | `RDReaderPageChildViewController` | PageCurl 模式子 VC | | `RDEpubReaderPageChildViewController.swift` | `RDEpubReaderPageChildViewController` | PageCurl 模式子 VC |
| `RDReaderView+PageCurl.swift` | Extension | UIPageViewController 数据源/代理 | | `RDEpubReaderView+PageCurl.swift` | Extension | UIPageViewController 数据源/代理 |
| `RDReaderView+CollectionView.swift` | Extension | UICollectionView 数据源/布局代理 | | `RDEpubReaderView+CollectionView.swift` | Extension | UICollectionView 数据源/布局代理 |
| `RDReaderView+ContentAccess.swift` | Extension | 内容视图访问与复用 | | `RDEpubReaderView+ContentAccess.swift` | Extension | 内容视图访问与复用 |
| `RDReaderView+ToolView.swift` | Extension | 工具栏安装与动画 | | `RDEpubReaderView+ToolView.swift` | Extension | 工具栏安装与动画 |
| `Paging/RDReaderPagingController.swift` | `RDReaderPagingController` | 翻页状态机 | | `Paging/RDEpubReaderPagingController.swift` | `RDEpubReaderPagingController` | 翻页状态机 |
| `Paging/RDReaderPreloadController.swift` | `RDReaderPreloadController` | 页面预加载与缓存 | | `Paging/RDEpubReaderPreloadController.swift` | `RDEpubReaderPreloadController` | 页面预加载与缓存 |
| `Paging/RDReaderSpreadResolver.swift` | `RDReaderSpreadResolver` | 双页展开计算 | | `Paging/RDEpubReaderSpreadResolver.swift` | `RDEpubReaderSpreadResolver` | 双页展开计算 |
| `Paging/RDReaderTapRegionHandler.swift` | `RDReaderTapRegionHandler` | 点击区域判定 | | `Paging/RDEpubReaderTapRegionHandler.swift` | `RDEpubReaderTapRegionHandler` | 点击区域判定 |
--- ---
## 2. 协议定义(RDReaderViewProtocols.swift ## 2. 协议定义(RDEpubReaderViewProtocols.swift
### 2.1 RDReaderDataSource(旧版数据源,已废弃) ### 2.1 RDEpubReaderDataSource(旧版数据源,已废弃)
```swift ```swift
@objc public protocol RDReaderDataSource: NSObjectProtocol { @objc public protocol RDEpubReaderDataSource: NSObjectProtocol {
func pageCountOfReaderView(readerView: RDReaderView) -> Int func pageCountOfReaderView(readerView: RDEpubReaderView) -> Int
func pageContentView(readerView: RDReaderView, pageNum: Int, containerView: UIView?) -> UIView func pageContentView(readerView: RDEpubReaderView, pageNum: Int, containerView: UIView?) -> UIView
func pageIdentifier(readerView: RDReaderView, pageNum: Int) -> String? func pageIdentifier(readerView: RDEpubReaderView, pageNum: Int) -> String?
@objc optional func topToolView(readerView: RDReaderView) -> UIView? @objc optional func topToolView(readerView: RDEpubReaderView) -> UIView?
@objc optional func bottomToolView(readerView: RDReaderView) -> UIView? @objc optional func bottomToolView(readerView: RDEpubReaderView) -> UIView?
} }
``` ```
> 向后兼容保留,新代码应使用 `RDReaderPageProvider`。 > 向后兼容保留,新代码应使用 `RDEpubReaderPageProvider`。
### 2.2 RDReaderPageProvider(推荐数据源) ### 2.2 RDEpubReaderPageProvider(推荐数据源)
```swift ```swift
@objc public protocol RDReaderPageProvider: NSObjectProtocol { @objc public protocol RDEpubReaderPageProvider: NSObjectProtocol {
func numberOfPages(in readerView: RDReaderView) -> Int func numberOfPages(in readerView: RDEpubReaderView) -> Int
func readerView(_ readerView: RDReaderView, viewForPageAt index: Int, reusableView: UIView?) -> UIView func readerView(_ readerView: RDEpubReaderView, viewForPageAt index: Int, reusableView: UIView?) -> UIView
@objc optional func pageIdentifier(in readerView: RDReaderView, index: Int) -> String? @objc optional func pageIdentifier(in readerView: RDEpubReaderView, index: Int) -> String?
@objc optional func readerViewTopChrome(_ readerView: RDReaderView) -> UIView? @objc optional func readerViewTopChrome(_ readerView: RDEpubReaderView) -> UIView?
@objc optional func readerViewBottomChrome(_ readerView: RDReaderView) -> UIView? @objc optional func readerViewBottomChrome(_ readerView: RDEpubReaderView) -> UIView?
} }
``` ```
@@ -65,31 +65,31 @@
| `readerViewTopChrome(_:)` | 返回顶部工具栏视图 | | `readerViewTopChrome(_:)` | 返回顶部工具栏视图 |
| `readerViewBottomChrome(_:)` | 返回底部工具栏视图 | | `readerViewBottomChrome(_:)` | 返回底部工具栏视图 |
### 2.3 RDReaderDelegate ### 2.3 RDEpubReaderDelegate
```swift ```swift
@objc public protocol RDReaderDelegate: NSObjectProtocol { @objc public protocol RDEpubReaderDelegate: NSObjectProtocol {
func pageNum(readerView: RDReaderView, pageNum: Int) func pageNum(readerView: RDEpubReaderView, pageNum: Int)
@objc optional func readerViewOrientationWillChange(readerView: RDReaderView, isLandscape: Bool) @objc optional func readerViewOrientationWillChange(readerView: RDEpubReaderView, isLandscape: Bool)
} }
``` ```
### 2.4 RDReaderPageNavigating ### 2.4 RDEpubReaderPageNavigating
```swift ```swift
public protocol RDReaderPageNavigating: AnyObject { public protocol RDEpubReaderPageNavigating: AnyObject {
var currentPage: Int { get } var currentPage: Int { get }
func reloadPages() func reloadPages()
func transition(to page: Int, animated: Bool) func transition(to page: Int, animated: Bool)
} }
``` ```
`RDReaderView` 遵循此协议,提供统一的页面导航接口。 `RDEpubReaderView` 遵循此协议,提供统一的页面导航接口。
### 2.5 枚举类型 ### 2.5 枚举类型
```swift ```swift
extension RDReaderView { extension RDEpubReaderView {
public enum DisplayType { public enum DisplayType {
case pageCurl // 仿UIPageViewController case pageCurl // 仿UIPageViewController
case horizontalScroll // UICollectionView case horizontalScroll // UICollectionView
@@ -105,13 +105,13 @@ extension RDReaderView {
--- ---
## 3. 核心类:RDReaderView ## 3. 核心类:RDEpubReaderView
**文件:** `RDReaderView.swift` **文件:** `RDEpubReaderView.swift`
`RDReaderView` 是一个 `UIView` 子类,作为翻页容器的主入口。内部管理两种翻页引擎: `RDEpubReaderView` 是一个 `UIView` 子类,作为翻页容器的主入口。内部管理两种翻页引擎:
- **PageCurl 模式**:使用 `UIPageViewController` 实现仿真翻页 - **PageCurl 模式**:使用 `UIPageViewController` 实现仿真翻页
- **Scroll 模式**:使用 `UICollectionView` + 自定义 `RDReaderFlowLayout` 实现滑动翻页 - **Scroll 模式**:使用 `UICollectionView` + 自定义 `RDEpubReaderFlowLayout` 实现滑动翻页
### 3.1 关键属性 ### 3.1 关键属性
@@ -124,16 +124,16 @@ extension RDReaderView {
| `coverPageIndex` | `Int?` | 封面页索引(独占一屏) | | `coverPageIndex` | `Int?` | 封面页索引(独占一屏) |
| `pagesPerScreen` | `Int` | 每屏页数(横屏双页时为 2) | | `pagesPerScreen` | `Int` | 每屏页数(横屏双页时为 2) |
| `preloadRadius` | `Int` | 预加载半径(默认 1 | | `preloadRadius` | `Int` | 预加载半径(默认 1 |
| `dataSource` | `RDReaderDataSource?` | 旧版数据源 | | `dataSource` | `RDEpubReaderDataSource?` | 旧版数据源 |
| `pageProvider` | `RDReaderPageProvider?` | 推荐数据源 | | `pageProvider` | `RDEpubReaderPageProvider?` | 推荐数据源 |
| `delegate` | `RDReaderDelegate?` | 事件代理 | | `delegate` | `RDEpubReaderDelegate?` | 事件代理 |
| `toolViewAnimationDuration` | `TimeInterval` | 工具栏动画时长(0.3s | | `toolViewAnimationDuration` | `TimeInterval` | 工具栏动画时长(0.3s |
### 3.2 关键方法 ### 3.2 关键方法
```swift ```swift
/// pageCurl / horizontalScroll / verticalScroll /// pageCurl / horizontalScroll / verticalScroll
public func switchReaderDisplayType(_ displayType: RDReaderView.DisplayType) public func switchReaderDisplayType(_ displayType: RDEpubReaderView.DisplayType)
/// ///
public func transitionToPage(pageNum: Int, animated: Bool = false) public func transitionToPage(pageNum: Int, animated: Bool = false)
@@ -154,22 +154,22 @@ public func isFullScreenPage(_ pageNum: Int) -> Bool
|------|------|------| |------|------|------|
| `pageViewController` | `UIPageViewController` | PageCurl 翻页引擎 | | `pageViewController` | `UIPageViewController` | PageCurl 翻页引擎 |
| `collectionView` | `UICollectionView` | Scroll 翻页引擎 | | `collectionView` | `UICollectionView` | Scroll 翻页引擎 |
| `layout` | `RDReaderFlowLayout` | CollectionView 自定义布局 | | `layout` | `RDEpubReaderFlowLayout` | CollectionView 自定义布局 |
| `spreadResolver` | `RDReaderSpreadResolver` | 双页配对计算 | | `spreadResolver` | `RDEpubReaderSpreadResolver` | 双页配对计算 |
| `tapRegionHandler` | `RDReaderTapRegionHandler` | 点击区域判定 | | `tapRegionHandler` | `RDEpubReaderTapRegionHandler` | 点击区域判定 |
| `preloadController` | `RDReaderPreloadController` | 页面预加载与缓存 | | `preloadController` | `RDEpubReaderPreloadController` | 页面预加载与缓存 |
| `pagingController` | `RDReaderPagingController` | 翻页状态管理 | | `pagingController` | `RDEpubReaderPagingController` | 翻页状态管理 |
--- ---
## 4. 翻页状态机:RDReaderPagingController ## 4. 翻页状态机:RDEpubReaderPagingController
**文件:** `Paging/RDReaderPagingController.swift` **文件:** `Paging/RDEpubReaderPagingController.swift`
管理 PageCurl 模式下的翻页请求队列,防止动画冲突。 管理 PageCurl 模式下的翻页请求队列,防止动画冲突。
```swift ```swift
struct RDReaderPagingController { struct RDEpubReaderPagingController {
struct PageTransitionRequest: Equatable { struct PageTransitionRequest: Equatable {
let pageNum: Int let pageNum: Int
let animated: Bool let animated: Bool
@@ -180,7 +180,7 @@ struct RDReaderPagingController {
var didBuildUI: Bool // UI var didBuildUI: Bool // UI
/// PageCurl true /// PageCurl true
mutating func shouldQueuePageTransition(_ request: PageTransitionRequest, currentDisplayType: RDReaderView.DisplayType) -> Bool mutating func shouldQueuePageTransition(_ request: PageTransitionRequest, currentDisplayType: RDEpubReaderView.DisplayType) -> Bool
/// ///
mutating func finishPageCurlTransition() -> PageTransitionRequest? mutating func finishPageCurlTransition() -> PageTransitionRequest?
@@ -192,9 +192,9 @@ struct RDReaderPagingController {
--- ---
## 5. 页面预加载:RDReaderPreloadController ## 5. 页面预加载:RDEpubReaderPreloadController
**文件:** `Paging/RDReaderPreloadController.swift` **文件:** `Paging/RDEpubReaderPreloadController.swift`
负责在当前页周围预渲染页面视图,减少翻页时的白屏时间。 负责在当前页周围预渲染页面视图,减少翻页时的白屏时间。
@@ -224,27 +224,27 @@ func invalidate(environment: Environment)
```swift ```swift
struct Environment { struct Environment {
let displayType: RDReaderView.DisplayType let displayType: RDEpubReaderView.DisplayType
let isLandscape: Bool let isLandscape: Bool
let pagesPerScreen: Int let pagesPerScreen: Int
let boundsSize: CGSize let boundsSize: CGSize
let landscapeDualPageEnabled: Bool let landscapeDualPageEnabled: Bool
let coverPageIndex: Int? let coverPageIndex: Int?
let totalPages: Int let totalPages: Int
let spreadResolver: RDReaderSpreadResolver let spreadResolver: RDEpubReaderSpreadResolver
} }
``` ```
--- ---
## 6. 双页展开计算:RDReaderSpreadResolver ## 6. 双页展开计算:RDEpubReaderSpreadResolver
**文件:** `Paging/RDReaderSpreadResolver.swift` **文件:** `Paging/RDEpubReaderSpreadResolver.swift`
纯函数式结构体,负责双页模式下的页面配对和导航计算。 纯函数式结构体,负责双页模式下的页面配对和导航计算。
```swift ```swift
struct RDReaderSpreadResolver { struct RDEpubReaderSpreadResolver {
/// ///
func isFullScreenPage(_ pageNum: Int, landscapeDualPageEnabled: Bool, isLandscape: Bool, coverPageIndex: Int?) -> Bool func isFullScreenPage(_ pageNum: Int, landscapeDualPageEnabled: Bool, isLandscape: Bool, coverPageIndex: Int?) -> Bool
@@ -265,15 +265,15 @@ struct RDReaderSpreadResolver {
--- ---
## 7. 点击区域判定:RDReaderTapRegionHandler ## 7. 点击区域判定:RDEpubReaderTapRegionHandler
**文件:** `Paging/RDReaderTapRegionHandler.swift` **文件:** `Paging/RDEpubReaderTapRegionHandler.swift`
将屏幕三等分,判定点击属于左/中/右区域。 将屏幕三等分,判定点击属于左/中/右区域。
```swift ```swift
struct RDReaderTapRegionHandler { struct RDEpubReaderTapRegionHandler {
func resolveTapEvent(point: CGPoint, viewFrame: CGRect, isToolViewVisible: Bool) -> RDReaderView.TapEvent func resolveTapEvent(point: CGPoint, viewFrame: CGRect, isToolViewVisible: Bool) -> RDEpubReaderView.TapEvent
} }
``` ```
@@ -284,9 +284,9 @@ struct RDReaderTapRegionHandler {
--- ---
## 8. 流式布局:RDReaderFlowLayout ## 8. 流式布局:RDEpubReaderFlowLayout
**文件:** `RDReaderFlowLayout.swift` **文件:** `RDEpubReaderFlowLayout.swift`
`UICollectionViewFlowLayout` 子类,支持水平滚动和垂直滚动两种模式。 `UICollectionViewFlowLayout` 子类,支持水平滚动和垂直滚动两种模式。
@@ -294,7 +294,7 @@ struct RDReaderTapRegionHandler {
| 属性 | 类型 | 说明 | | 属性 | 类型 | 说明 |
|------|------|------| |------|------|------|
| `displayType` | `RDReaderView.DisplayType` | 布局模式 | | `displayType` | `RDEpubReaderView.DisplayType` | 布局模式 |
| `isLandscapeDualPage` | `Bool` | 是否横屏双页 | | `isLandscapeDualPage` | `Bool` | 是否横屏双页 |
| `coverPageIndex` | `Int?` | 封面页索引 | | `coverPageIndex` | `Int?` | 封面页索引 |
| `pagesPerScreen` | `Int` | 每屏页数 | | `pagesPerScreen` | `Int` | 每屏页数 |
@@ -302,12 +302,12 @@ struct RDReaderTapRegionHandler {
### 8.2 协议 ### 8.2 协议
```swift ```swift
public protocol RDReaderFlowLayoutDataSoure: NSObjectProtocol { public protocol RDEpubReaderFlowLayoutDataSoure: NSObjectProtocol {
func heigtOfVerticalScrollPage(flowLayout: RDReaderFlowLayout, pageIndex: Int) -> CGFloat? func heigtOfVerticalScrollPage(flowLayout: RDEpubReaderFlowLayout, pageIndex: Int) -> CGFloat?
} }
@objc public protocol RDReaderFlowLayoutDelegate: NSObjectProtocol { @objc public protocol RDEpubReaderFlowLayoutDelegate: NSObjectProtocol {
func pageNum(flowLayout: RDReaderFlowLayout, pageIndex: Int) func pageNum(flowLayout: RDEpubReaderFlowLayout, pageIndex: Int)
} }
``` ```
@@ -324,28 +324,28 @@ func currentContentOffset(count: Int) -> CGPoint
--- ---
## 9. 内容 CellRDReaderContentCell ## 9. 内容 CellRDEpubReaderContentCell
**文件:** `RDReaderContentCell.swift` **文件:** `RDEpubReaderContentCell.swift`
`UICollectionViewCell` 子类,用于 Scroll 模式下承载页面内容视图。 `UICollectionViewCell` 子类,用于 Scroll 模式下承载页面内容视图。
```swift ```swift
class RDReaderContentCell: UICollectionViewCell { class RDEpubReaderContentCell: UICollectionViewCell {
var containerView: UIView? // contentView var containerView: UIView? // contentView
} }
``` ```
--- ---
## 10. PageCurl 子控制器:RDReaderPageChildViewController ## 10. PageCurl 子控制器:RDEpubReaderPageChildViewController
**文件:** `RDReaderPageChildViewController.swift` **文件:** `RDEpubReaderPageChildViewController.swift`
`UIViewController` 子类,作为 `UIPageViewController` 的页面 VC。 `UIViewController` 子类,作为 `UIPageViewController` 的页面 VC。
```swift ```swift
class RDReaderPageChildViewController: UIViewController { class RDEpubReaderPageChildViewController: UIViewController {
var contentView: UIView? // var contentView: UIView? //
var pageNum: Int // var pageNum: Int //
@@ -357,7 +357,7 @@ class RDReaderPageChildViewController: UIViewController {
## 11. Extension 汇总 ## 11. Extension 汇总
### 11.1 RDReaderView+PageCurl ### 11.1 RDEpubReaderView+PageCurl
实现 `UIPageViewControllerDataSource``UIPageViewControllerDelegate` 实现 `UIPageViewControllerDataSource``UIPageViewControllerDelegate`
@@ -367,18 +367,18 @@ class RDReaderPageChildViewController: UIViewController {
- `pageViewController(_:willTransitionTo:)` — 即将翻页时预加载 - `pageViewController(_:willTransitionTo:)` — 即将翻页时预加载
**特殊页码:** **特殊页码:**
- `RDReaderView.blankPageNum``Int.max`)— 双页模式下的空白页 - `RDEpubReaderView.blankPageNum``Int.max`)— 双页模式下的空白页
- `RDReaderView.blankEndPageNum``Int.max - 1`)— 末尾空白页 - `RDEpubReaderView.blankEndPageNum``Int.max - 1`)— 末尾空白页
### 11.2 RDReaderView+CollectionView ### 11.2 RDEpubReaderView+CollectionView
实现 `UICollectionViewDataSource``RDReaderFlowLayoutDelegate``RDReaderFlowLayoutDataSoure` 实现 `UICollectionViewDataSource``RDEpubReaderFlowLayoutDelegate``RDEpubReaderFlowLayoutDataSoure`
- `collectionView(_:cellForItemAt:)` — 复用预加载视图或创建新 Cell - `collectionView(_:cellForItemAt:)` — 复用预加载视图或创建新 Cell
- `collectionView(_:numberOfItemsInSection:)` — 返回总页数 - `collectionView(_:numberOfItemsInSection:)` — 返回总页数
- `pageNum(flowLayout:pageIndex:)` — 滚动时更新当前页码 - `pageNum(flowLayout:pageIndex:)` — 滚动时更新当前页码
### 11.3 RDReaderView+ContentAccess ### 11.3 RDEpubReaderView+ContentAccess
提供内容视图的注册、复用和查询: 提供内容视图的注册、复用和查询:
@@ -396,7 +396,7 @@ public func pageContentView(pageNum: Int) -> UIView?
public func resolvedSinglePageSize(pageNum: Int? = nil) -> CGSize public func resolvedSinglePageSize(pageNum: Int? = nil) -> CGSize
``` ```
### 11.4 RDReaderView+ToolView ### 11.4 RDEpubReaderView+ToolView
管理顶部/底部工具栏的安装、显示/隐藏动画: 管理顶部/底部工具栏的安装、显示/隐藏动画:
@@ -420,11 +420,11 @@ func updateToolViewHeightConstraintsIfNeeded()
| 模式 | 应用 | | 模式 | 应用 |
|------|------| |------|------|
| **策略模式** | `DisplayType` 切换 PageCurl / Scroll 两种翻页策略 | | **策略模式** | `DisplayType` 切换 PageCurl / Scroll 两种翻页策略 |
| **适配器模式** | `RDReaderLegacyDataSourceAdapter` 将旧 `RDReaderDataSource` 适配为 `RDReaderPageProvider` | | **适配器模式** | `RDEpubReaderLegacyDataSourceAdapter` 将旧 `RDEpubReaderDataSource` 适配为 `RDEpubReaderPageProvider` |
| **命令队列** | `RDReaderPagingController` 管理翻页请求队列 | | **命令队列** | `RDEpubReaderPagingController` 管理翻页请求队列 |
| **缓存签名** | `RDReaderPreloadController.CacheSignature` 检测环境变化自动失效 | | **缓存签名** | `RDEpubReaderPreloadController.CacheSignature` 检测环境变化自动失效 |
| **关注点分离** | Extension 将不同功能拆分到独立文件 | | **关注点分离** | Extension 将不同功能拆分到独立文件 |
| **纯函数** | `RDReaderSpreadResolver``RDReaderTapRegionHandler` 无状态计算 | | **纯函数** | `RDEpubReaderSpreadResolver``RDEpubReaderTapRegionHandler` 无状态计算 |
--- ---
@@ -434,7 +434,7 @@ func updateToolViewHeightConstraintsIfNeeded()
用户点击屏幕 用户点击屏幕
RDReaderTapRegionHandler.resolveTapEvent() RDEpubReaderTapRegionHandler.resolveTapEvent()
├── .left → goPreviousPage() ──→ spreadResolver.nextPage(forward: false) ├── .left → goPreviousPage() ──→ spreadResolver.nextPage(forward: false)
├── .right → goNextPage() ──→ spreadResolver.nextPage(forward: true) ├── .right → goNextPage() ──→ spreadResolver.nextPage(forward: true)
+4 -4
View File
@@ -64,13 +64,13 @@
### CocoaPods 依赖准备 ### CocoaPods 依赖准备
> 仓库包含示例工程 `ReadViewDemo`,并已提交 `Pods/` 与 `Podfile.lock`。如本地环境未同步,可在仓库根或示例工程目录运行: > 仓库包含示例工程 `ReadViewDemo`,并已提交 `ReadViewDemo/Pods/` 与 `ReadViewDemo/Podfile.lock`。如本地环境未同步,请在示例工程目录运行:
```bash ```bash
pod install cd ReadViewDemo && pod install
``` ```
(依赖入口:`Podfile``ReadViewDemo/Podfile` (依赖入口:`ReadViewDemo/Podfile`
### 运行 UI 测试 ### 运行 UI 测试
@@ -116,7 +116,7 @@ xcodebuild test \
建议同时记录以下观测项: 建议同时记录以下观测项:
- `prepareOnDemandChapter` 主线程 wall clock - `prepareOnDemandChapter` 主线程 wall clock
- `RDReaderPreloadController` 预加载命中率 - `RDEpubReaderPreloadController` 预加载命中率
- `bookPageMap` partial extension / full replacement 次数 - `bookPageMap` partial extension / full replacement 次数
- 页面静态底图缓存命中率 - 页面静态底图缓存命中率
- CFI 延迟构建完成次数与耗时 - CFI 延迟构建完成次数与耗时
+1 -1
View File
@@ -16,7 +16,7 @@
**输出**`RDEPUBTypesettingOutput`(渲染请求、诊断信息、兼容性报告) **输出**`RDEPUBTypesettingOutput`(渲染请求、诊断信息、兼容性报告)
**关键文件**`Sources/RDReaderView/EPUBTextRendering/Typesetter/` **关键文件**`Sources/RDEpubReaderView/EPUBTextRendering/Typesetter/`
--- ---
+28 -28
View File
@@ -31,12 +31,12 @@ graph TB
IndexTable[RDEPUBTextIndexTable] IndexTable[RDEPUBTextIndexTable]
end end
subgraph RDReaderView subgraph RDEpubReaderView
ReaderView[RDReaderView] ReaderView[RDEpubReaderView]
FlowLayout[RDReaderFlowLayout] FlowLayout[RDEpubReaderFlowLayout]
Preload[RDReaderPreloadController] Preload[RDEpubReaderPreloadController]
Spread[RDReaderSpreadResolver] Spread[RDEpubReaderSpreadResolver]
TapRegion[RDReaderTapRegionHandler] TapRegion[RDEpubReaderTapRegionHandler]
end end
subgraph EPUBUI subgraph EPUBUI
@@ -297,11 +297,11 @@ classDiagram
```mermaid ```mermaid
classDiagram classDiagram
class RDReaderView { class RDEpubReaderView {
+currentPage: Int +currentPage: Int
+currentDisplayType: DisplayType +currentDisplayType: DisplayType
+pageProvider: RDReaderPageProvider? +pageProvider: RDEpubReaderPageProvider?
+delegate: RDReaderDelegate? +delegate: RDEpubReaderDelegate?
+landscapeDualPageEnabled: Bool +landscapeDualPageEnabled: Bool
+pageDirection: PageDirection +pageDirection: PageDirection
+coverPageIndex: Int? +coverPageIndex: Int?
@@ -318,14 +318,14 @@ classDiagram
verticalScroll verticalScroll
} }
class RDReaderPageProvider { class RDEpubReaderPageProvider {
<<protocol>> <<protocol>>
+numberOfPages(in:) Int +numberOfPages(in:) Int
+readerView(_:viewForPageAt:reusableView:) UIView +readerView(_:viewForPageAt:reusableView:) UIView
+pageIdentifier(in:index:) String? +pageIdentifier(in:index:) String?
} }
class RDReaderFlowLayout { class RDEpubReaderFlowLayout {
+displayType: DisplayType +displayType: DisplayType
+isLandscapeDualPage: Bool +isLandscapeDualPage: Bool
+coverPageIndex: Int? +coverPageIndex: Int?
@@ -333,7 +333,7 @@ classDiagram
+currentPage: Int +currentPage: Int
} }
class RDReaderPreloadController { class RDEpubReaderPreloadController {
+radius: Int +radius: Int
+pageViewForDisplay(pageNum:environment:contentViewProvider:) UIView? +pageViewForDisplay(pageNum:environment:contentViewProvider:) UIView?
+takePreloadedView(for:) UIView? +takePreloadedView(for:) UIView?
@@ -341,13 +341,13 @@ classDiagram
+invalidate(environment:) +invalidate(environment:)
} }
class RDReaderSpreadResolver { class RDEpubReaderSpreadResolver {
+isFullScreenPage(...) Bool +isFullScreenPage(...) Bool
+dualPagePair(for:totalPages:coverPageIndex:) (Int, Int?) +dualPagePair(for:totalPages:coverPageIndex:) (Int, Int?)
+nextPage(from:totalPages:pagesPerScreen:coverPageIndex:forward:) Int? +nextPage(from:totalPages:pagesPerScreen:coverPageIndex:forward:) Int?
} }
class RDReaderTapRegionHandler { class RDEpubReaderTapRegionHandler {
+resolveTapEvent(point:viewFrame:isToolViewVisible:) TapEvent +resolveTapEvent(point:viewFrame:isToolViewVisible:) TapEvent
} }
@@ -359,7 +359,7 @@ classDiagram
right right
} }
class RDReaderPagingController { class RDEpubReaderPagingController {
+isTransitioning: Bool +isTransitioning: Bool
+didBuildUI: Bool +didBuildUI: Bool
+pendingTransitionRequest: PageTransitionRequest? +pendingTransitionRequest: PageTransitionRequest?
@@ -367,25 +367,25 @@ classDiagram
+finishPageCurlTransition() PageTransitionRequest? +finishPageCurlTransition() PageTransitionRequest?
} }
class RDReaderContentCell { class RDEpubReaderContentCell {
+containerView: UIView? +containerView: UIView?
} }
class RDReaderPageChildViewController { class RDEpubReaderPageChildViewController {
+contentView: UIView? +contentView: UIView?
+pageNum: Int +pageNum: Int
} }
RDReaderView --> DisplayType : uses RDEpubReaderView --> DisplayType : uses
RDReaderView --> RDReaderPageProvider : delegates RDEpubReaderView --> RDEpubReaderPageProvider : delegates
RDReaderView --> RDReaderFlowLayout : owns RDEpubReaderView --> RDEpubReaderFlowLayout : owns
RDReaderView --> RDReaderPreloadController : owns RDEpubReaderView --> RDEpubReaderPreloadController : owns
RDReaderView --> RDReaderSpreadResolver : owns RDEpubReaderView --> RDEpubReaderSpreadResolver : owns
RDReaderView --> RDReaderTapRegionHandler : owns RDEpubReaderView --> RDEpubReaderTapRegionHandler : owns
RDReaderView --> RDReaderPagingController : owns RDEpubReaderView --> RDEpubReaderPagingController : owns
RDReaderView --> RDReaderContentCell : creates RDEpubReaderView --> RDEpubReaderContentCell : creates
RDReaderView --> RDReaderPageChildViewController : creates RDEpubReaderView --> RDEpubReaderPageChildViewController : creates
RDReaderTapRegionHandler --> TapEvent : produces RDEpubReaderTapRegionHandler --> TapEvent : produces
``` ```
--- ---
@@ -403,7 +403,7 @@ classDiagram
+highlights: [RDEPUBHighlight] +highlights: [RDEPUBHighlight]
+bookmarks: [RDEPUBBookmark] +bookmarks: [RDEPUBBookmark]
+tableOfContents: [EPUBTableOfContentsItem] +tableOfContents: [EPUBTableOfContentsItem]
+readerView: RDReaderView +readerView: RDEpubReaderView
+readerContext: RDEPUBReaderContext +readerContext: RDEPUBReaderContext
+runtime: RDEPUBReaderRuntime? +runtime: RDEPUBReaderRuntime?
} }
+1 -1
View File
@@ -47,7 +47,7 @@
## 项目信息 ## 项目信息
- **模块总数:** 4 个(EPUBCore、EPUBTextRendering、RDReaderView、EPUBUI - **模块总数:** 4 个(EPUBCore、EPUBTextRendering、RDEpubReaderView、EPUBUI
- **Swift 文件数:** 142 个(SDK Sources - **Swift 文件数:** 142 个(SDK Sources
- **测试用例数:** 23 个测试类,约 99 个测试方法(UI 测试) - **测试用例数:** 23 个测试类,约 99 个测试方法(UI 测试)
- **最低 iOS 版本:** 15.6 - **最低 iOS 版本:** 15.6
-30
View File
@@ -1,30 +0,0 @@
platform :ios, '15.6'
use_frameworks!
workspace 'ReadViewSDK.xcworkspace'
project 'ReadViewSDK.xcodeproj'
target 'ReadViewSDK' do
pod 'RDReaderView', :path => '..'
end
post_install do |installer|
apply_settings = lambda do |config|
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.6'
end
# Pods project (Pods.xcodeproj)
installer.pods_project.build_configurations.each { |c| apply_settings.call(c) }
installer.pods_project.targets.each { |t| t.build_configurations.each { |c| apply_settings.call(c) } }
installer.aggregate_targets.each do |at|
p = at.user_project
next unless p
# User project(s) that integrate Pods (e.g. ReadViewDemo / ReadViewSDK)
p.build_configurations.each { |c| apply_settings.call(c) }
p.targets.each { |t| t.build_configurations.each { |c| apply_settings.call(c) } }
p.save
end
end
+19
View File
@@ -0,0 +1,19 @@
Pod::Spec.new do |s|
s.name = "RDEpubReaderView"
s.module_name = "RDEpubReaderView"
s.version = "0.0.1"
s.summary = "A reader view for EPUB and plain-text books"
s.platform = :ios, "15.0"
s.swift_versions = ["5.10"]
s.homepage = "http://192.168.21.200:8418/4v5u09Z5a4Yuc/ReadViewSDK.git"
s.author = { "shenlei" => "shenlei@touchread.com" }
s.source = { :git => "http://192.168.21.200:8418/4v5u09Z5a4Yuc/ReadViewSDK.git", :tag => "#{s.version}" }
s.license = "MIT"
s.source_files = "Sources/RDEpubReaderView/**/*.{swift}"
s.resource_bundles = {
"RDEpubReaderViewAssets" => ["Sources/RDEpubReaderView/EPUBCore/Resources/**/*"]
}
s.dependency "ZIPFoundation", "~> 0.9"
s.dependency "DTCoreText", "~> 1.6"
s.requires_arc = true
end
-21
View File
@@ -1,21 +0,0 @@
Pod::Spec.new do |s|
s.name = "RDReaderView"
s.version = "0.0.1"
s.summary = "A reader view for novel"
s.platform = :ios, "15.6"
s.swift_versions = ["5.10"]
s.homepage = "https://github.com/namesubai/RDReaderView.git"
s.author = { "subai" => "804663401@qq.com" }
s.source = { :git => "https://github.com/namesubai/RDReaderView.git", :tag => "#{s.version}"}
s.license = "MIT"
s.source_files = 'Sources/RDReaderView/**/*.{swift}'
s.resource_bundles = {
'RDReaderViewAssets' => ['Sources/RDReaderView/EPUBCore/Resources/**/*']
}
s.dependency 'ZIPFoundation', '~> 0.9'
s.dependency 'DTCoreText', '~> 1.6'
s.requires_arc = true
end
+3 -2
View File
@@ -3,14 +3,15 @@ platform :ios, '15.6'
target 'ReadViewDemo' do target 'ReadViewDemo' do
# Comment the next line if you don't want to use dynamic frameworks # Comment the next line if you don't want to use dynamic frameworks
use_frameworks! use_frameworks!
pod 'RDReaderView', :path => '..' pod 'RDEpubReaderView', :path => '../Sources/RDEpubReaderView'
pod 'RDPDFReaderView', :path => '../Sources/RDPDFReaderView'
end end
post_install do |installer| post_install do |installer|
apply_settings = lambda do |config| apply_settings = lambda do |config|
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO' config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.6' config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
end end
# Pods project (Pods.xcodeproj) # Pods project (Pods.xcodeproj)
+16 -6
View File
@@ -16,30 +16,40 @@ PODS:
- DTFoundation/Core - DTFoundation/Core
- DTFoundation/UIKit (1.7.19): - DTFoundation/UIKit (1.7.19):
- DTFoundation/Core - DTFoundation/Core
- RDReaderView (0.0.1): - RDEpubReaderView (0.0.2):
- DTCoreText (~> 1.6) - DTCoreText (~> 1.6)
- SnapKit (~> 5.7)
- ZIPFoundation (~> 0.9) - ZIPFoundation (~> 0.9)
- RDPDFReaderView (0.0.1):
- SnapKit (~> 5.7)
- SnapKit (5.7.1)
- ZIPFoundation (0.9.20) - ZIPFoundation (0.9.20)
DEPENDENCIES: DEPENDENCIES:
- RDReaderView (from `..`) - RDEpubReaderView (from `../Sources/RDEpubReaderView`)
- RDPDFReaderView (from `../Sources/RDPDFReaderView`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- DTCoreText - DTCoreText
- DTFoundation - DTFoundation
- SnapKit
- ZIPFoundation - ZIPFoundation
EXTERNAL SOURCES: EXTERNAL SOURCES:
RDReaderView: RDEpubReaderView:
:path: ".." :path: "../Sources/RDEpubReaderView"
RDPDFReaderView:
:path: "../Sources/RDPDFReaderView"
SPEC CHECKSUMS: SPEC CHECKSUMS:
DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb
DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0 DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0
RDReaderView: 2e0eeeff4bcfe8bbc09642344d326440af280ed5 RDEpubReaderView: 5a09a7856f04b6f2f8610aa6fd965d35cadb8e17
RDPDFReaderView: f7c2d0ea7c129aa4ab15ae7f9daad2974573d749
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351 ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351
PODFILE CHECKSUM: 775f5c8c488024e24d494aad6331e9fef8f9e2e5 PODFILE CHECKSUM: c39db27dbc9c6a96a33f22e78ce1b22dcd48d75f
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2
@@ -0,0 +1,40 @@
{
"name": "RDEpubReaderView",
"module_name": "RDEpubReaderView",
"version": "0.0.2",
"summary": "A reader view for EPUB, TXT, MOBI, and CBZ books",
"platforms": {
"ios": "15.0"
},
"swift_versions": [
"5.10"
],
"homepage": "http://192.168.21.200:8418/4v5u09Z5a4Yuc/ReadViewSDK.git",
"authors": {
"shenlei": "shenlei@touchread.com"
},
"source": {
"git": "http://192.168.21.200:8418/4v5u09Z5a4Yuc/ReadViewSDK.git",
"tag": "0.0.2"
},
"license": "MIT",
"source_files": "**/*.swift",
"resource_bundles": {
"RDEpubReaderViewAssets": [
"EPUBCore/Resources/**/*"
]
},
"dependencies": {
"ZIPFoundation": [
"~> 0.9"
],
"DTCoreText": [
"~> 1.6"
],
"SnapKit": [
"~> 5.7"
]
},
"requires_arc": true,
"swift_version": "5.10"
}
@@ -0,0 +1,33 @@
{
"name": "RDPDFReaderView",
"module_name": "RDPDFReaderView",
"version": "0.0.1",
"summary": "UIKit PDF reader supporting host images and direct PDFKit parsing",
"platforms": {
"ios": "15.0"
},
"swift_versions": [
"5.10"
],
"homepage": "https://example.invalid/RDPDFReaderView",
"authors": {
"readoor": "ios@touchread.com"
},
"source": {
"path": "."
},
"license": "MIT",
"source_files": "{Sources,ReaderView}/**/*.swift",
"dependencies": {
"SnapKit": [
"~> 5.7"
]
},
"frameworks": [
"Vision",
"CoreImage",
"PDFKit"
],
"requires_arc": true,
"swift_version": "5.10"
}
@@ -1,36 +0,0 @@
{
"name": "RDReaderView",
"version": "0.0.1",
"summary": "A reader view for novel",
"platforms": {
"ios": "15.6"
},
"swift_versions": [
"5.10"
],
"homepage": "https://github.com/namesubai/RDReaderView.git",
"authors": {
"subai": "804663401@qq.com"
},
"source": {
"git": "https://github.com/namesubai/RDReaderView.git",
"tag": "0.0.1"
},
"license": "MIT",
"source_files": "Sources/RDReaderView/**/*.{swift}",
"resource_bundles": {
"RDReaderViewAssets": [
"Sources/RDReaderView/EPUBCore/Resources/**/*"
]
},
"dependencies": {
"ZIPFoundation": [
"~> 0.9"
],
"DTCoreText": [
"~> 1.6"
]
},
"requires_arc": true,
"swift_version": "5.10"
}
+16 -6
View File
@@ -16,30 +16,40 @@ PODS:
- DTFoundation/Core - DTFoundation/Core
- DTFoundation/UIKit (1.7.19): - DTFoundation/UIKit (1.7.19):
- DTFoundation/Core - DTFoundation/Core
- RDReaderView (0.0.1): - RDEpubReaderView (0.0.2):
- DTCoreText (~> 1.6) - DTCoreText (~> 1.6)
- SnapKit (~> 5.7)
- ZIPFoundation (~> 0.9) - ZIPFoundation (~> 0.9)
- RDPDFReaderView (0.0.1):
- SnapKit (~> 5.7)
- SnapKit (5.7.1)
- ZIPFoundation (0.9.20) - ZIPFoundation (0.9.20)
DEPENDENCIES: DEPENDENCIES:
- RDReaderView (from `..`) - RDEpubReaderView (from `../Sources/RDEpubReaderView`)
- RDPDFReaderView (from `../Sources/RDPDFReaderView`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- DTCoreText - DTCoreText
- DTFoundation - DTFoundation
- SnapKit
- ZIPFoundation - ZIPFoundation
EXTERNAL SOURCES: EXTERNAL SOURCES:
RDReaderView: RDEpubReaderView:
:path: ".." :path: "../Sources/RDEpubReaderView"
RDPDFReaderView:
:path: "../Sources/RDPDFReaderView"
SPEC CHECKSUMS: SPEC CHECKSUMS:
DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb
DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0 DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0
RDReaderView: 2e0eeeff4bcfe8bbc09642344d326440af280ed5 RDEpubReaderView: 5a09a7856f04b6f2f8610aa6fd965d35cadb8e17
RDPDFReaderView: f7c2d0ea7c129aa4ab15ae7f9daad2974573d749
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351 ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351
PODFILE CHECKSUM: 775f5c8c488024e24d494aad6331e9fef8f9e2e5 PODFILE CHECKSUM: c39db27dbc9c6a96a33f22e78ce1b22dcd48d75f
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+155
View File
@@ -0,0 +1,155 @@
<img src="https://snapkit.github.io/SnapKit/images/banner.jpg" alt="" />
SnapKit is a DSL to make Auto Layout easy on both iOS and OS X.
[![Build Status](https://travis-ci.org/SnapKit/SnapKit.svg)](https://travis-ci.org/SnapKit/SnapKit)
[![Platform](https://img.shields.io/cocoapods/p/SnapKit.svg?style=flat)](https://github.com/SnapKit/SnapKit)
[![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SnapKit.svg)](https://cocoapods.org/pods/SnapKit)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
#### ⚠️ **To use with Swift 4.x please ensure you are using >= 4.0.0** ⚠️
#### ⚠️ **To use with Swift 5.x please ensure you are using >= 5.0.0** ⚠️
## Contents
- [Requirements](#requirements)
- [Migration Guides](#migration-guides)
- [Communication](#communication)
- [Installation](#installation)
- [Usage](#usage)
- [Credits](#credits)
- [License](#license)
## Requirements
- iOS 12.0+ / Mac OS X 10.13+ / tvOS 10.0+
- Xcode 10.0+
- Swift 4.0+
## Migration Guides
- [SnapKit 3.0 Migration Guide](Documentation/SnapKit%203.0%20Migration%20Guide.md)
## Communication
- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit). (Tag 'snapkit')
- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit).
- If you **found a bug**, open an issue.
- If you **have a feature request**, open an issue.
- If you **want to contribute**, submit a pull request.
## Installation
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
```bash
$ gem install cocoapods
```
> CocoaPods 1.1.0+ is required to build SnapKit 4.0.0+.
To integrate SnapKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'SnapKit', '~> 5.7.0'
end
```
Then, run the following command:
```bash
$ pod install
```
### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate SnapKit into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "SnapKit/SnapKit" ~> 5.0.0
```
Run `carthage update` to build the framework and drag the built `SnapKit.framework` into your Xcode project.
### Swift Package Manager
[Swift Package Manager](https://swift.org/package-manager/) is a tool for managing the distribution of Swift code. Its integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
> Xcode 11+ is required to build SnapKit using Swift Package Manager.
To integrate SnapKit into your Xcode project using Swift Package Manager, add it to the dependencies value of your `Package.swift`:
```swift
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1"))
]
```
### Manually
If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually.
---
## Usage
### Quick Start
```swift
import SnapKit
class MyViewController: UIViewController {
lazy var box = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(box)
box.backgroundColor = .green
box.snp.makeConstraints { (make) -> Void in
make.width.height.equalTo(50)
make.center.equalTo(self.view)
}
}
}
```
### Playground
You can try SnapKit in Playground.
**Note:**
> To try SnapKit in playground, open `SnapKit.xcworkspace` and build SnapKit.framework for any simulator first.
### Resources
- [Documentation](https://snapkit.github.io/SnapKit/docs/)
- [F.A.Q.](https://snapkit.github.io/SnapKit/faq/)
## Credits
- Robert Payne ([@robertjpayne](https://twitter.com/robertjpayne))
- Many other contributors
## License
SnapKit is released under the MIT license. See LICENSE for details.
+341
View File
@@ -0,0 +1,341 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public final class Constraint {
internal let sourceLocation: (String, UInt)
internal let label: String?
private let from: ConstraintItem
private let to: ConstraintItem
private let relation: ConstraintRelation
private let multiplier: ConstraintMultiplierTarget
private var constant: ConstraintConstantTarget {
didSet {
self.updateConstantAndPriorityIfNeeded()
}
}
private var priority: ConstraintPriorityTarget {
didSet {
self.updateConstantAndPriorityIfNeeded()
}
}
public var layoutConstraints: [LayoutConstraint]
public var isActive: Bool {
set {
if newValue {
activate()
}
else {
deactivate()
}
}
get {
for layoutConstraint in self.layoutConstraints {
if layoutConstraint.isActive {
return true
}
}
return false
}
}
// MARK: Initialization
internal init(from: ConstraintItem,
to: ConstraintItem,
relation: ConstraintRelation,
sourceLocation: (String, UInt),
label: String?,
multiplier: ConstraintMultiplierTarget,
constant: ConstraintConstantTarget,
priority: ConstraintPriorityTarget) {
self.from = from
self.to = to
self.relation = relation
self.sourceLocation = sourceLocation
self.label = label
self.multiplier = multiplier
self.constant = constant
self.priority = priority
self.layoutConstraints = []
// get attributes
let layoutFromAttributes = self.from.attributes.layoutAttributes
let layoutToAttributes = self.to.attributes.layoutAttributes
// get layout from
let layoutFrom = self.from.layoutConstraintItem!
// get relation
let layoutRelation = self.relation.layoutRelation
for layoutFromAttribute in layoutFromAttributes {
// get layout to attribute
let layoutToAttribute: LayoutAttribute
#if canImport(UIKit)
if layoutToAttributes.count > 0 {
if self.from.attributes == .edges && self.to.attributes == .margins {
switch layoutFromAttribute {
case .left:
layoutToAttribute = .leftMargin
case .right:
layoutToAttribute = .rightMargin
case .top:
layoutToAttribute = .topMargin
case .bottom:
layoutToAttribute = .bottomMargin
default:
fatalError()
}
} else if self.from.attributes == .margins && self.to.attributes == .edges {
switch layoutFromAttribute {
case .leftMargin:
layoutToAttribute = .left
case .rightMargin:
layoutToAttribute = .right
case .topMargin:
layoutToAttribute = .top
case .bottomMargin:
layoutToAttribute = .bottom
default:
fatalError()
}
} else if self.from.attributes == .directionalEdges && self.to.attributes == .directionalMargins {
switch layoutFromAttribute {
case .leading:
layoutToAttribute = .leadingMargin
case .trailing:
layoutToAttribute = .trailingMargin
case .top:
layoutToAttribute = .topMargin
case .bottom:
layoutToAttribute = .bottomMargin
default:
fatalError()
}
} else if self.from.attributes == .directionalMargins && self.to.attributes == .directionalEdges {
switch layoutFromAttribute {
case .leadingMargin:
layoutToAttribute = .leading
case .trailingMargin:
layoutToAttribute = .trailing
case .topMargin:
layoutToAttribute = .top
case .bottomMargin:
layoutToAttribute = .bottom
default:
fatalError()
}
} else if self.from.attributes == self.to.attributes {
layoutToAttribute = layoutFromAttribute
} else {
layoutToAttribute = layoutToAttributes[0]
}
} else {
if self.to.target == nil && (layoutFromAttribute == .centerX || layoutFromAttribute == .centerY) {
layoutToAttribute = layoutFromAttribute == .centerX ? .left : .top
} else {
layoutToAttribute = layoutFromAttribute
}
}
#else
if self.from.attributes == self.to.attributes {
layoutToAttribute = layoutFromAttribute
} else if layoutToAttributes.count > 0 {
layoutToAttribute = layoutToAttributes[0]
} else {
layoutToAttribute = layoutFromAttribute
}
#endif
// get layout constant
let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute)
// get layout to
var layoutTo: AnyObject? = self.to.target
// use superview if possible
if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height {
layoutTo = layoutFrom.superview
}
// create layout constraint
let layoutConstraint = LayoutConstraint(
item: layoutFrom,
attribute: layoutFromAttribute,
relatedBy: layoutRelation,
toItem: layoutTo,
attribute: layoutToAttribute,
multiplier: self.multiplier.constraintMultiplierTargetValue,
constant: layoutConstant
)
// set label
layoutConstraint.label = self.label
// set priority
layoutConstraint.priority = LayoutPriority(rawValue: self.priority.constraintPriorityTargetValue)
// set constraint
layoutConstraint.constraint = self
// append
self.layoutConstraints.append(layoutConstraint)
}
}
// MARK: Public
@available(*, deprecated, renamed:"activate()")
public func install() {
self.activate()
}
@available(*, deprecated, renamed:"deactivate()")
public func uninstall() {
self.deactivate()
}
public func activate() {
self.activateIfNeeded()
}
public func deactivate() {
self.deactivateIfNeeded()
}
@discardableResult
public func update(offset: ConstraintOffsetTarget) -> Constraint {
self.constant = offset.constraintOffsetTargetValue
return self
}
@discardableResult
public func update(inset: ConstraintInsetTarget) -> Constraint {
self.constant = inset.constraintInsetTargetValue
return self
}
#if canImport(UIKit)
@discardableResult
@available(iOS 11.0, tvOS 11.0, *)
public func update(inset: ConstraintDirectionalInsetTarget) -> Constraint {
self.constant = inset.constraintDirectionalInsetTargetValue
return self
}
#endif
@discardableResult
public func update(priority: ConstraintPriorityTarget) -> Constraint {
self.priority = priority.constraintPriorityTargetValue
return self
}
@discardableResult
public func update(priority: ConstraintPriority) -> Constraint {
self.priority = priority.value
return self
}
@available(*, deprecated, renamed:"update(offset:)")
public func updateOffset(amount: ConstraintOffsetTarget) -> Void { self.update(offset: amount) }
@available(*, deprecated, renamed:"update(inset:)")
public func updateInsets(amount: ConstraintInsetTarget) -> Void { self.update(inset: amount) }
@available(*, deprecated, renamed:"update(priority:)")
public func updatePriority(amount: ConstraintPriorityTarget) -> Void { self.update(priority: amount) }
@available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityRequired() -> Void {}
@available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") }
@available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") }
@available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") }
// MARK: Internal
internal func updateConstantAndPriorityIfNeeded() {
for layoutConstraint in self.layoutConstraints {
let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute
layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute)
let requiredPriority = ConstraintPriority.required.value
if (layoutConstraint.priority.rawValue < requiredPriority), (self.priority.constraintPriorityTargetValue != requiredPriority) {
layoutConstraint.priority = LayoutPriority(rawValue: self.priority.constraintPriorityTargetValue)
}
}
}
internal func activateIfNeeded(updatingExisting: Bool = false) {
guard let item = self.from.layoutConstraintItem else {
print("WARNING: SnapKit failed to get from item from constraint. Activate will be a no-op.")
return
}
let layoutConstraints = self.layoutConstraints
if updatingExisting {
var existingLayoutConstraints: [LayoutConstraint] = []
for constraint in item.constraints {
existingLayoutConstraints += constraint.layoutConstraints
}
for layoutConstraint in layoutConstraints {
let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint }
guard let updateLayoutConstraint = existingLayoutConstraint else {
fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)")
}
let updateLayoutAttribute = (updateLayoutConstraint.secondAttribute == .notAnAttribute) ? updateLayoutConstraint.firstAttribute : updateLayoutConstraint.secondAttribute
updateLayoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: updateLayoutAttribute)
}
} else {
NSLayoutConstraint.activate(layoutConstraints)
item.add(constraints: [self])
}
}
internal func deactivateIfNeeded() {
guard let item = self.from.layoutConstraintItem else {
print("WARNING: SnapKit failed to get from item from constraint. Deactivate will be a no-op.")
return
}
let layoutConstraints = self.layoutConstraints
NSLayoutConstraint.deactivate(layoutConstraints)
item.remove(constraints: [self])
}
}
@@ -0,0 +1,203 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
internal struct ConstraintAttributes : OptionSet, ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = UInt
internal init(rawValue: UInt) {
self.rawValue = rawValue
}
internal init(_ rawValue: UInt) {
self.init(rawValue: rawValue)
}
internal init(nilLiteral: ()) {
self.rawValue = 0
}
internal init(integerLiteral rawValue: IntegerLiteralType) {
self.init(rawValue: rawValue)
}
internal private(set) var rawValue: UInt
internal static var allZeros: ConstraintAttributes { return 0 }
internal static func convertFromNilLiteral() -> ConstraintAttributes { return 0 }
internal var boolValue: Bool { return self.rawValue != 0 }
internal func toRaw() -> UInt { return self.rawValue }
internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) }
// normal
internal static let none: ConstraintAttributes = 0
internal static let left: ConstraintAttributes = ConstraintAttributes(UInt(1) << 0)
internal static let top: ConstraintAttributes = ConstraintAttributes(UInt(1) << 1)
internal static let right: ConstraintAttributes = ConstraintAttributes(UInt(1) << 2)
internal static let bottom: ConstraintAttributes = ConstraintAttributes(UInt(1) << 3)
internal static let leading: ConstraintAttributes = ConstraintAttributes(UInt(1) << 4)
internal static let trailing: ConstraintAttributes = ConstraintAttributes(UInt(1) << 5)
internal static let width: ConstraintAttributes = ConstraintAttributes(UInt(1) << 6)
internal static let height: ConstraintAttributes = ConstraintAttributes(UInt(1) << 7)
internal static let centerX: ConstraintAttributes = ConstraintAttributes(UInt(1) << 8)
internal static let centerY: ConstraintAttributes = ConstraintAttributes(UInt(1) << 9)
internal static let lastBaseline: ConstraintAttributes = ConstraintAttributes(UInt(1) << 10)
@available(iOS 8.0, OSX 10.11, *)
internal static let firstBaseline: ConstraintAttributes = ConstraintAttributes(UInt(1) << 11)
@available(iOS 8.0, *)
internal static let leftMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 12)
@available(iOS 8.0, *)
internal static let rightMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 13)
@available(iOS 8.0, *)
internal static let topMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 14)
@available(iOS 8.0, *)
internal static let bottomMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 15)
@available(iOS 8.0, *)
internal static let leadingMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 16)
@available(iOS 8.0, *)
internal static let trailingMargin: ConstraintAttributes = ConstraintAttributes(UInt(1) << 17)
@available(iOS 8.0, *)
internal static let centerXWithinMargins: ConstraintAttributes = ConstraintAttributes(UInt(1) << 18)
@available(iOS 8.0, *)
internal static let centerYWithinMargins: ConstraintAttributes = ConstraintAttributes(UInt(1) << 19)
// aggregates
internal static let edges: ConstraintAttributes = [.horizontalEdges, .verticalEdges]
internal static let horizontalEdges: ConstraintAttributes = [.left, .right]
internal static let verticalEdges: ConstraintAttributes = [.top, .bottom]
internal static let directionalEdges: ConstraintAttributes = [.directionalHorizontalEdges, .directionalVerticalEdges]
internal static let directionalHorizontalEdges: ConstraintAttributes = [.leading, .trailing]
internal static let directionalVerticalEdges: ConstraintAttributes = [.top, .bottom]
internal static let size: ConstraintAttributes = [.width, .height]
internal static let center: ConstraintAttributes = [.centerX, .centerY]
@available(iOS 8.0, *)
internal static let margins: ConstraintAttributes = [.leftMargin, .topMargin, .rightMargin, .bottomMargin]
@available(iOS 8.0, *)
internal static let directionalMargins: ConstraintAttributes = [.leadingMargin, .topMargin, .trailingMargin, .bottomMargin]
@available(iOS 8.0, *)
internal static let centerWithinMargins: ConstraintAttributes = [.centerXWithinMargins, .centerYWithinMargins]
internal var layoutAttributes:[LayoutAttribute] {
var attrs = [LayoutAttribute]()
if (self.contains(ConstraintAttributes.left)) {
attrs.append(.left)
}
if (self.contains(ConstraintAttributes.top)) {
attrs.append(.top)
}
if (self.contains(ConstraintAttributes.right)) {
attrs.append(.right)
}
if (self.contains(ConstraintAttributes.bottom)) {
attrs.append(.bottom)
}
if (self.contains(ConstraintAttributes.leading)) {
attrs.append(.leading)
}
if (self.contains(ConstraintAttributes.trailing)) {
attrs.append(.trailing)
}
if (self.contains(ConstraintAttributes.width)) {
attrs.append(.width)
}
if (self.contains(ConstraintAttributes.height)) {
attrs.append(.height)
}
if (self.contains(ConstraintAttributes.centerX)) {
attrs.append(.centerX)
}
if (self.contains(ConstraintAttributes.centerY)) {
attrs.append(.centerY)
}
if (self.contains(ConstraintAttributes.lastBaseline)) {
attrs.append(.lastBaseline)
}
#if canImport(UIKit)
if (self.contains(ConstraintAttributes.firstBaseline)) {
attrs.append(.firstBaseline)
}
if (self.contains(ConstraintAttributes.leftMargin)) {
attrs.append(.leftMargin)
}
if (self.contains(ConstraintAttributes.rightMargin)) {
attrs.append(.rightMargin)
}
if (self.contains(ConstraintAttributes.topMargin)) {
attrs.append(.topMargin)
}
if (self.contains(ConstraintAttributes.bottomMargin)) {
attrs.append(.bottomMargin)
}
if (self.contains(ConstraintAttributes.leadingMargin)) {
attrs.append(.leadingMargin)
}
if (self.contains(ConstraintAttributes.trailingMargin)) {
attrs.append(.trailingMargin)
}
if (self.contains(ConstraintAttributes.centerXWithinMargins)) {
attrs.append(.centerXWithinMargins)
}
if (self.contains(ConstraintAttributes.centerYWithinMargins)) {
attrs.append(.centerYWithinMargins)
}
#endif
return attrs
}
}
internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes {
return left.union(right)
}
internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.formUnion(right)
}
internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.subtract(right)
}
internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool {
return left.rawValue == right.rawValue
}
+37
View File
@@ -0,0 +1,37 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection
#else
import AppKit
public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection
#endif
public struct ConstraintConfig {
public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight
}
@@ -0,0 +1,213 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintConstantTarget {
}
extension CGPoint: ConstraintConstantTarget {
}
extension CGSize: ConstraintConstantTarget {
}
extension ConstraintInsets: ConstraintConstantTarget {
}
#if canImport(UIKit)
@available(iOS 11.0, tvOS 11.0, *)
extension ConstraintDirectionalInsets: ConstraintConstantTarget {
}
#endif
extension ConstraintConstantTarget {
internal func constraintConstantTargetValueFor(layoutAttribute: LayoutAttribute) -> CGFloat {
if let value = self as? CGFloat {
return value
}
if let value = self as? Float {
return CGFloat(value)
}
if let value = self as? Double {
return CGFloat(value)
}
if let value = self as? Int {
return CGFloat(value)
}
if let value = self as? UInt {
return CGFloat(value)
}
if let value = self as? CGSize {
if layoutAttribute == .width {
return value.width
} else if layoutAttribute == .height {
return value.height
} else {
return 0.0
}
}
if let value = self as? CGPoint {
#if canImport(UIKit)
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins:
return value.x
case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
#if swift(>=5.0)
@unknown default:
return 0.0
#endif
}
#else
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX:
return value.x
case .top, .bottom, .centerY, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
#if swift(>=5.0)
@unknown default:
return 0.0
#endif
}
#endif
}
if let value = self as? ConstraintInsets {
#if canImport(UIKit)
switch layoutAttribute {
case .left, .leftMargin:
return value.left
case .top, .topMargin, .firstBaseline:
return value.top
case .right, .rightMargin:
return -value.right
case .bottom, .bottomMargin, .lastBaseline:
return -value.bottom
case .leading, .leadingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right
case .trailing, .trailingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left
case .centerX, .centerXWithinMargins:
return (value.left - value.right) / 2
case .centerY, .centerYWithinMargins:
return (value.top - value.bottom) / 2
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
#if swift(>=5.0)
@unknown default:
return 0.0
#endif
}
#else
switch layoutAttribute {
case .left:
return value.left
case .top, .firstBaseline:
return value.top
case .right:
return -value.right
case .bottom, .lastBaseline:
return -value.bottom
case .leading:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right
case .trailing:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left
case .centerX:
return (value.left - value.right) / 2
case .centerY:
return (value.top - value.bottom) / 2
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
#if swift(>=5.0)
@unknown default:
return 0.0
#endif
}
#endif
}
#if canImport(UIKit)
if #available(iOS 11.0, tvOS 11.0, *), let value = self as? ConstraintDirectionalInsets {
switch layoutAttribute {
case .left, .leftMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.leading : value.trailing
case .top, .topMargin, .firstBaseline:
return value.top
case .right, .rightMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.trailing : -value.leading
case .bottom, .bottomMargin, .lastBaseline:
return -value.bottom
case .leading, .leadingMargin:
return value.leading
case .trailing, .trailingMargin:
return -value.trailing
case .centerX, .centerXWithinMargins:
return (value.leading - value.trailing) / 2
case .centerY, .centerYWithinMargins:
return (value.top - value.bottom) / 2
case .width:
return -(value.leading + value.trailing)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
#if swift(>=5.0)
@unknown default:
return 0.0
#else
default:
return 0.0
#endif
}
}
#endif
return 0.0
}
}
+209
View File
@@ -0,0 +1,209 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintDSL {
var target: AnyObject? { get }
func setLabel(_ value: String?)
func label() -> String?
}
extension ConstraintDSL {
public func setLabel(_ value: String?) {
objc_setAssociatedObject(self.target as Any, &labelKey, value, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
public func label() -> String? {
return objc_getAssociatedObject(self.target as Any, &labelKey) as? String
}
}
private var labelKey: UInt8 = 0
public protocol ConstraintBasicAttributesDSL : ConstraintDSL {
}
extension ConstraintBasicAttributesDSL {
// MARK: Basics
public var left: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left)
}
public var top: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
}
public var right: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right)
}
public var bottom: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
}
public var leading: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading)
}
public var trailing: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing)
}
public var width: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width)
}
public var height: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
}
public var centerX: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX)
}
public var centerY: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY)
}
public var edges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges)
}
public var directionalEdges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalEdges)
}
public var horizontalEdges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.horizontalEdges)
}
public var verticalEdges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.verticalEdges)
}
public var directionalHorizontalEdges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalHorizontalEdges)
}
public var directionalVerticalEdges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalVerticalEdges)
}
public var size: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size)
}
public var center: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center)
}
}
public protocol ConstraintAttributesDSL : ConstraintBasicAttributesDSL {
}
extension ConstraintAttributesDSL {
// MARK: Baselines
@available(*, deprecated, renamed:"lastBaseline")
public var baseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var lastBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline)
}
// MARK: Margins
@available(iOS 8.0, *)
public var leftMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin)
}
@available(iOS 8.0, *)
public var topMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin)
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin)
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin)
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin)
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin)
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins)
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins)
}
@available(iOS 8.0, *)
public var margins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins)
}
@available(iOS 8.0, *)
public var directionalMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalMargins)
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins)
}
}
@@ -0,0 +1,69 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintDescription {
internal let item: LayoutConstraintItem
internal var attributes: ConstraintAttributes
internal var relation: ConstraintRelation? = nil
internal var sourceLocation: (String, UInt)? = nil
internal var label: String? = nil
internal var related: ConstraintItem? = nil
internal var multiplier: ConstraintMultiplierTarget = 1.0
internal var constant: ConstraintConstantTarget = 0.0
internal var priority: ConstraintPriorityTarget = 1000.0
internal lazy var constraint: Constraint? = {
guard let relation = self.relation,
let related = self.related,
let sourceLocation = self.sourceLocation else {
return nil
}
let from = ConstraintItem(target: self.item, attributes: self.attributes)
return Constraint(
from: from,
to: related,
relation: relation,
sourceLocation: sourceLocation,
label: self.label,
multiplier: self.multiplier,
constant: self.constant,
priority: self.priority
)
}()
// MARK: Initialization
internal init(item: LayoutConstraintItem, attributes: ConstraintAttributes) {
self.item = item
self.attributes = attributes
}
}
@@ -0,0 +1,49 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
public protocol ConstraintDirectionalInsetTarget: ConstraintConstantTarget {
}
@available(iOS 11.0, tvOS 11.0, *)
extension ConstraintDirectionalInsets: ConstraintDirectionalInsetTarget {
}
extension ConstraintDirectionalInsetTarget {
@available(iOS 11.0, tvOS 11.0, *)
internal var constraintDirectionalInsetTargetValue: ConstraintDirectionalInsets {
if let amount = self as? ConstraintDirectionalInsets {
return amount
} else {
return ConstraintDirectionalInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
}
}
}
#endif
@@ -0,0 +1,34 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
@available(iOS 11.0, tvOS 11.0, *)
public typealias ConstraintDirectionalInsets = NSDirectionalEdgeInsets
#endif
@@ -0,0 +1,72 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintInsetTarget: ConstraintConstantTarget {
}
extension Int: ConstraintInsetTarget {
}
extension UInt: ConstraintInsetTarget {
}
extension Float: ConstraintInsetTarget {
}
extension Double: ConstraintInsetTarget {
}
extension CGFloat: ConstraintInsetTarget {
}
extension ConstraintInsets: ConstraintInsetTarget {
}
extension ConstraintInsetTarget {
internal var constraintInsetTargetValue: ConstraintInsets {
if let amount = self as? ConstraintInsets {
return amount
} else if let amount = self as? Float {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? Double {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? CGFloat {
return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount)
} else if let amount = self as? Int {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? UInt {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else {
return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
}
+35
View File
@@ -0,0 +1,35 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
public typealias ConstraintInsets = UIEdgeInsets
#else
public typealias ConstraintInsets = NSEdgeInsets
#endif
+61
View File
@@ -0,0 +1,61 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public final class ConstraintItem {
internal weak var target: AnyObject?
internal let attributes: ConstraintAttributes
internal init(target: AnyObject?, attributes: ConstraintAttributes) {
self.target = target
self.attributes = attributes
}
internal var layoutConstraintItem: LayoutConstraintItem? {
return self.target as? LayoutConstraintItem
}
}
public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool {
// pointer equality
guard lhs !== rhs else {
return true
}
// must both have valid targets and identical attributes
guard let target1 = lhs.target,
let target2 = rhs.target,
target1 === target2 && lhs.attributes == rhs.attributes else {
return false
}
return true
}
@@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#endif
@available(iOS 9.0, OSX 10.11, *)
public extension ConstraintLayoutGuide {
var snp: ConstraintLayoutGuideDSL {
return ConstraintLayoutGuideDSL(guide: self)
}
}
@@ -0,0 +1,37 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
@available(iOS 9.0, *)
public typealias ConstraintLayoutGuide = UILayoutGuide
#else
@available(OSX 10.11, *)
public typealias ConstraintLayoutGuide = NSLayoutGuide
#endif
@@ -0,0 +1,66 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
@available(iOS 9.0, OSX 10.11, *)
public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL {
@discardableResult
public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
return ConstraintMaker.prepareConstraints(item: self.guide, closure: closure)
}
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.makeConstraints(item: self.guide, closure: closure)
}
public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.remakeConstraints(item: self.guide, closure: closure)
}
public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.updateConstraints(item: self.guide, closure: closure)
}
public func removeConstraints() {
ConstraintMaker.removeConstraints(item: self.guide)
}
public var target: AnyObject? {
return self.guide
}
internal let guide: ConstraintLayoutGuide
internal init(guide: ConstraintLayoutGuide) {
self.guide = guide
}
}
@@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
@available(iOS 8.0, *)
public typealias ConstraintLayoutSupport = UILayoutSupport
#else
public class ConstraintLayoutSupport {}
#endif
@@ -0,0 +1,56 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
@available(iOS 8.0, *)
public struct ConstraintLayoutSupportDSL: ConstraintDSL {
public var target: AnyObject? {
return self.support
}
internal let support: ConstraintLayoutSupport
internal init(support: ConstraintLayoutSupport) {
self.support = support
}
public var top: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
}
public var bottom: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
}
public var height: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
}
}
+224
View File
@@ -0,0 +1,224 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintMaker {
public var left: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.left)
}
public var top: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.top)
}
public var bottom: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.bottom)
}
public var right: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.right)
}
public var leading: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leading)
}
public var trailing: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.trailing)
}
public var width: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.width)
}
public var height: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.height)
}
public var centerX: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerX)
}
public var centerY: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerY)
}
@available(*, deprecated, renamed:"lastBaseline")
public var baseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.lastBaseline)
}
public var lastBaseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.firstBaseline)
}
@available(iOS 8.0, *)
public var leftMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leftMargin)
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.rightMargin)
}
@available(iOS 8.0, *)
public var topMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.topMargin)
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.bottomMargin)
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leadingMargin)
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.trailingMargin)
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerXWithinMargins)
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerYWithinMargins)
}
public var edges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.edges)
}
public var horizontalEdges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.horizontalEdges)
}
public var verticalEdges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.verticalEdges)
}
public var directionalEdges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.directionalEdges)
}
public var directionalHorizontalEdges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.directionalHorizontalEdges)
}
public var directionalVerticalEdges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.directionalVerticalEdges)
}
public var size: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.size)
}
public var center: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.center)
}
@available(iOS 8.0, *)
public var margins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.margins)
}
@available(iOS 8.0, *)
public var directionalMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.directionalMargins)
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerWithinMargins)
}
public let item: LayoutConstraintItem
private var descriptions = [ConstraintDescription]()
internal init(item: LayoutConstraintItem) {
self.item = item
self.item.prepare()
}
internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
let description = ConstraintDescription(item: self.item, attributes: attributes)
self.descriptions.append(description)
return ConstraintMakerExtendable(description)
}
internal static func prepareConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
let maker = ConstraintMaker(item: item)
closure(maker)
var constraints: [Constraint] = []
for description in maker.descriptions {
guard let constraint = description.constraint else {
continue
}
constraints.append(constraint)
}
return constraints
}
internal static func makeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
let constraints = prepareConstraints(item: item, closure: closure)
for constraint in constraints {
constraint.activateIfNeeded(updatingExisting: false)
}
}
internal static func remakeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
self.removeConstraints(item: item)
self.makeConstraints(item: item, closure: closure)
}
internal static func updateConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
guard item.constraints.count > 0 else {
self.makeConstraints(item: item, closure: closure)
return
}
let constraints = prepareConstraints(item: item, closure: closure)
for constraint in constraints {
constraint.activateIfNeeded(updatingExisting: true)
}
}
internal static func removeConstraints(item: LayoutConstraintItem) {
let constraints = item.constraints
for constraint in constraints {
constraint.deactivateIfNeeded()
}
}
}
@@ -0,0 +1,64 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerEditable: ConstraintMakerPrioritizable {
@discardableResult
public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
self.description.multiplier = amount
return self
}
@discardableResult
public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue)
}
@discardableResult
public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable {
self.description.constant = amount.constraintOffsetTargetValue
return self
}
@discardableResult
public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable {
self.description.constant = amount.constraintInsetTargetValue
return self
}
#if canImport(UIKit)
@discardableResult
@available(iOS 11.0, tvOS 11.0, *)
public func inset(_ amount: ConstraintDirectionalInsetTarget) -> ConstraintMakerEditable {
self.description.constant = amount.constraintDirectionalInsetTargetValue
return self
}
#endif
}
@@ -0,0 +1,195 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerExtendable: ConstraintMakerRelatable {
public var left: ConstraintMakerExtendable {
self.description.attributes += .left
return self
}
public var top: ConstraintMakerExtendable {
self.description.attributes += .top
return self
}
public var bottom: ConstraintMakerExtendable {
self.description.attributes += .bottom
return self
}
public var right: ConstraintMakerExtendable {
self.description.attributes += .right
return self
}
public var leading: ConstraintMakerExtendable {
self.description.attributes += .leading
return self
}
public var trailing: ConstraintMakerExtendable {
self.description.attributes += .trailing
return self
}
public var width: ConstraintMakerExtendable {
self.description.attributes += .width
return self
}
public var height: ConstraintMakerExtendable {
self.description.attributes += .height
return self
}
public var centerX: ConstraintMakerExtendable {
self.description.attributes += .centerX
return self
}
public var centerY: ConstraintMakerExtendable {
self.description.attributes += .centerY
return self
}
@available(*, deprecated, renamed:"lastBaseline")
public var baseline: ConstraintMakerExtendable {
self.description.attributes += .lastBaseline
return self
}
public var lastBaseline: ConstraintMakerExtendable {
self.description.attributes += .lastBaseline
return self
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintMakerExtendable {
self.description.attributes += .firstBaseline
return self
}
@available(iOS 8.0, *)
public var leftMargin: ConstraintMakerExtendable {
self.description.attributes += .leftMargin
return self
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintMakerExtendable {
self.description.attributes += .rightMargin
return self
}
@available(iOS 8.0, *)
public var topMargin: ConstraintMakerExtendable {
self.description.attributes += .topMargin
return self
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintMakerExtendable {
self.description.attributes += .bottomMargin
return self
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintMakerExtendable {
self.description.attributes += .leadingMargin
return self
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintMakerExtendable {
self.description.attributes += .trailingMargin
return self
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerXWithinMargins
return self
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerYWithinMargins
return self
}
public var edges: ConstraintMakerExtendable {
self.description.attributes += .edges
return self
}
public var horizontalEdges: ConstraintMakerExtendable {
self.description.attributes += .horizontalEdges
return self
}
public var verticalEdges: ConstraintMakerExtendable {
self.description.attributes += .verticalEdges
return self
}
public var directionalEdges: ConstraintMakerExtendable {
self.description.attributes += .directionalEdges
return self
}
public var directionalHorizontalEdges: ConstraintMakerExtendable {
self.description.attributes += .directionalHorizontalEdges
return self
}
public var directionalVerticalEdges: ConstraintMakerExtendable {
self.description.attributes += .directionalVerticalEdges
return self
}
public var size: ConstraintMakerExtendable {
self.description.attributes += .size
return self
}
@available(iOS 8.0, *)
public var margins: ConstraintMakerExtendable {
self.description.attributes += .margins
return self
}
@available(iOS 8.0, *)
public var directionalMargins: ConstraintMakerExtendable {
self.description.attributes += .directionalMargins
return self
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerWithinMargins
return self
}
}
@@ -0,0 +1,49 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerFinalizable {
internal let description: ConstraintDescription
internal init(_ description: ConstraintDescription) {
self.description = description
}
@discardableResult
public func labeled(_ label: String) -> ConstraintMakerFinalizable {
self.description.label = label
return self
}
public var constraint: Constraint {
return self.description.constraint!
}
}
@@ -0,0 +1,70 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
@available(*, deprecated, message:"Use ConstraintMakerPrioritizable instead.")
public typealias ConstraintMakerPriortizable = ConstraintMakerPrioritizable
public class ConstraintMakerPrioritizable: ConstraintMakerFinalizable {
@discardableResult
public func priority(_ amount: ConstraintPriority) -> ConstraintMakerFinalizable {
self.description.priority = amount.value
return self
}
@discardableResult
public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable {
self.description.priority = amount
return self
}
@available(*, deprecated, message:"Use priority(.required) instead.")
@discardableResult
public func priorityRequired() -> ConstraintMakerFinalizable {
return self.priority(.required)
}
@available(*, deprecated, message:"Use priority(.high) instead.")
@discardableResult
public func priorityHigh() -> ConstraintMakerFinalizable {
return self.priority(.high)
}
@available(*, deprecated, message:"Use priority(.medium) instead.")
@discardableResult
public func priorityMedium() -> ConstraintMakerFinalizable {
return self.priority(.medium)
}
@available(*, deprecated, message:"Use priority(.low) instead.")
@discardableResult
public func priorityLow() -> ConstraintMakerFinalizable {
return self.priority(.low)
}
}
@@ -0,0 +1,57 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
extension ConstraintMakerRelatable {
@discardableResult
public func equalToSuperview<T: ConstraintRelatableTarget>(_ closure: (ConstraintView) -> T, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
}
return self.relatedTo(closure(other), relation: .equal, file: file, line: line)
}
@discardableResult
public func lessThanOrEqualToSuperview<T: ConstraintRelatableTarget>(_ closure: (ConstraintView) -> T, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `lessThanOrEqualToSuperview`.")
}
return self.relatedTo(closure(other), relation: .lessThanOrEqual, file: file, line: line)
}
@discardableResult
public func greaterThanOrEqualToSuperview<T: ConstraintRelatableTarget>(_ closure: (ConstraintView) -> T, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.")
}
return self.relatedTo(closure(other), relation: .greaterThanOrEqual, file: file, line: line)
}
}
@@ -0,0 +1,115 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerRelatable {
internal let description: ConstraintDescription
internal init(_ description: ConstraintDescription) {
self.description = description
}
internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable {
let related: ConstraintItem
let constant: ConstraintConstantTarget
if let other = other as? ConstraintItem {
guard other.attributes == ConstraintAttributes.none ||
other.attributes.layoutAttributes.count <= 1 ||
other.attributes.layoutAttributes == self.description.attributes.layoutAttributes ||
other.attributes == .edges && self.description.attributes == .margins ||
other.attributes == .margins && self.description.attributes == .edges ||
other.attributes == .directionalEdges && self.description.attributes == .directionalMargins ||
other.attributes == .directionalMargins && self.description.attributes == .directionalEdges else {
fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))");
}
related = other
constant = 0.0
} else if let other = other as? ConstraintView {
related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
constant = 0.0
} else if let other = other as? ConstraintConstantTarget {
related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none)
constant = other
} else if #available(iOS 9.0, OSX 10.11, *), let other = other as? ConstraintLayoutGuide {
related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
constant = 0.0
} else {
fatalError("Invalid constraint. (\(file), \(line))")
}
let editable = ConstraintMakerEditable(self.description)
editable.description.sourceLocation = (file, line)
editable.description.relation = relation
editable.description.related = related
editable.description.constant = constant
return editable
}
@discardableResult
public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .equal, file: file, line: line)
}
@discardableResult
public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
}
return self.relatedTo(other, relation: .equal, file: file, line: line)
}
@discardableResult
public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
}
@discardableResult
public func lessThanOrEqualToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `lessThanOrEqualToSuperview`.")
}
return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
}
@discardableResult
public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
}
@discardableResult
public func greaterThanOrEqualToSuperview(_ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.item.superview else {
fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.")
}
return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
}
}
@@ -0,0 +1,75 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintMultiplierTarget {
var constraintMultiplierTargetValue: CGFloat { get }
}
extension Int: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension UInt: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension Float: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension Double: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension CGFloat: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return self
}
}
@@ -0,0 +1,69 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintOffsetTarget: ConstraintConstantTarget {
}
extension Int: ConstraintOffsetTarget {
}
extension UInt: ConstraintOffsetTarget {
}
extension Float: ConstraintOffsetTarget {
}
extension Double: ConstraintOffsetTarget {
}
extension CGFloat: ConstraintOffsetTarget {
}
extension ConstraintOffsetTarget {
internal var constraintOffsetTargetValue: CGFloat {
let offset: CGFloat
if let amount = self as? Float {
offset = CGFloat(amount)
} else if let amount = self as? Double {
offset = CGFloat(amount)
} else if let amount = self as? CGFloat {
offset = CGFloat(amount)
} else if let amount = self as? Int {
offset = CGFloat(amount)
} else if let amount = self as? UInt {
offset = CGFloat(amount)
} else {
offset = 0.0
}
return offset
}
}
@@ -0,0 +1,77 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public struct ConstraintPriority : ExpressibleByFloatLiteral, Equatable, Strideable {
public typealias FloatLiteralType = Float
public let value: Float
public init(floatLiteral value: Float) {
self.value = value
}
public init(_ value: Float) {
self.value = value
}
public static var required: ConstraintPriority {
return 1000.0
}
public static var high: ConstraintPriority {
return 750.0
}
public static var medium: ConstraintPriority {
#if os(OSX)
return 501.0
#else
return 500.0
#endif
}
public static var low: ConstraintPriority {
return 250.0
}
public static func ==(lhs: ConstraintPriority, rhs: ConstraintPriority) -> Bool {
return lhs.value == rhs.value
}
// MARK: Strideable
public func advanced(by n: FloatLiteralType) -> ConstraintPriority {
return ConstraintPriority(floatLiteral: value + n)
}
public func distance(to other: ConstraintPriority) -> FloatLiteralType {
return other.value - value
}
}
@@ -0,0 +1,85 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintPriorityTarget {
var constraintPriorityTargetValue: Float { get }
}
extension Int: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension UInt: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension Float: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return self
}
}
extension Double: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension CGFloat: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
#if canImport(UIKit)
extension UILayoutPriority: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return self.rawValue
}
}
#endif
@@ -0,0 +1,72 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintRelatableTarget {
}
extension Int: ConstraintRelatableTarget {
}
extension UInt: ConstraintRelatableTarget {
}
extension Float: ConstraintRelatableTarget {
}
extension Double: ConstraintRelatableTarget {
}
extension CGFloat: ConstraintRelatableTarget {
}
extension CGSize: ConstraintRelatableTarget {
}
extension CGPoint: ConstraintRelatableTarget {
}
extension ConstraintInsets: ConstraintRelatableTarget {
}
#if canImport(UIKit)
@available(iOS 11.0, tvOS 11.0, *)
extension ConstraintDirectionalInsets: ConstraintRelatableTarget {
}
#endif
extension ConstraintItem: ConstraintRelatableTarget {
}
extension ConstraintView: ConstraintRelatableTarget {
}
@available(iOS 9.0, OSX 10.11, *)
extension ConstraintLayoutGuide: ConstraintRelatableTarget {
}
@@ -0,0 +1,48 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
internal enum ConstraintRelation : Int {
case equal = 1
case lessThanOrEqual
case greaterThanOrEqual
internal var layoutRelation: LayoutRelation {
get {
switch(self) {
case .equal:
return .equal
case .lessThanOrEqual:
return .lessThanOrEqual
case .greaterThanOrEqual:
return .greaterThanOrEqual
}
}
}
}
@@ -0,0 +1,152 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public extension ConstraintView {
@available(*, deprecated, renamed:"snp.left")
var snp_left: ConstraintItem { return self.snp.left }
@available(*, deprecated, renamed:"snp.top")
var snp_top: ConstraintItem { return self.snp.top }
@available(*, deprecated, renamed:"snp.right")
var snp_right: ConstraintItem { return self.snp.right }
@available(*, deprecated, renamed:"snp.bottom")
var snp_bottom: ConstraintItem { return self.snp.bottom }
@available(*, deprecated, renamed:"snp.leading")
var snp_leading: ConstraintItem { return self.snp.leading }
@available(*, deprecated, renamed:"snp.trailing")
var snp_trailing: ConstraintItem { return self.snp.trailing }
@available(*, deprecated, renamed:"snp.width")
var snp_width: ConstraintItem { return self.snp.width }
@available(*, deprecated, renamed:"snp.height")
var snp_height: ConstraintItem { return self.snp.height }
@available(*, deprecated, renamed:"snp.centerX")
var snp_centerX: ConstraintItem { return self.snp.centerX }
@available(*, deprecated, renamed:"snp.centerY")
var snp_centerY: ConstraintItem { return self.snp.centerY }
@available(*, deprecated, renamed:"snp.baseline")
var snp_baseline: ConstraintItem { return self.snp.baseline }
@available(*, deprecated, renamed:"snp.lastBaseline")
@available(iOS 8.0, OSX 10.11, *)
var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline }
@available(iOS, deprecated, renamed:"snp.firstBaseline")
@available(iOS 8.0, OSX 10.11, *)
var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline }
@available(iOS, deprecated, renamed:"snp.leftMargin")
@available(iOS 8.0, *)
var snp_leftMargin: ConstraintItem { return self.snp.leftMargin }
@available(iOS, deprecated, renamed:"snp.topMargin")
@available(iOS 8.0, *)
var snp_topMargin: ConstraintItem { return self.snp.topMargin }
@available(iOS, deprecated, renamed:"snp.rightMargin")
@available(iOS 8.0, *)
var snp_rightMargin: ConstraintItem { return self.snp.rightMargin }
@available(iOS, deprecated, renamed:"snp.bottomMargin")
@available(iOS 8.0, *)
var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin }
@available(iOS, deprecated, renamed:"snp.leadingMargin")
@available(iOS 8.0, *)
var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin }
@available(iOS, deprecated, renamed:"snp.trailingMargin")
@available(iOS 8.0, *)
var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin }
@available(iOS, deprecated, renamed:"snp.centerXWithinMargins")
@available(iOS 8.0, *)
var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins }
@available(iOS, deprecated, renamed:"snp.centerYWithinMargins")
@available(iOS 8.0, *)
var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins }
@available(*, deprecated, renamed:"snp.edges")
var snp_edges: ConstraintItem { return self.snp.edges }
@available(*, deprecated, renamed:"snp.size")
var snp_size: ConstraintItem { return self.snp.size }
@available(*, deprecated, renamed:"snp.center")
var snp_center: ConstraintItem { return self.snp.center }
@available(iOS, deprecated, renamed:"snp.margins")
@available(iOS 8.0, *)
var snp_margins: ConstraintItem { return self.snp.margins }
@available(iOS, deprecated, renamed:"snp.centerWithinMargins")
@available(iOS 8.0, *)
var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins }
@available(*, deprecated, renamed:"snp.prepareConstraints(_:)")
func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
return self.snp.prepareConstraints(closure)
}
@available(*, deprecated, renamed:"snp.makeConstraints(_:)")
func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.makeConstraints(closure)
}
@available(*, deprecated, renamed:"snp.remakeConstraints(_:)")
func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.remakeConstraints(closure)
}
@available(*, deprecated, renamed:"snp.updateConstraints(_:)")
func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.updateConstraints(closure)
}
@available(*, deprecated, renamed:"snp.removeConstraints()")
func snp_removeConstraints() {
self.snp.removeConstraints()
}
var snp: ConstraintViewDSL {
return ConstraintViewDSL(view: self)
}
}
+35
View File
@@ -0,0 +1,35 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
#if canImport(UIKit)
public typealias ConstraintView = UIView
#else
public typealias ConstraintView = NSView
#endif
+101
View File
@@ -0,0 +1,101 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public struct ConstraintViewDSL: ConstraintAttributesDSL {
@discardableResult
public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
return ConstraintMaker.prepareConstraints(item: self.view, closure: closure)
}
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.makeConstraints(item: self.view, closure: closure)
}
public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.remakeConstraints(item: self.view, closure: closure)
}
public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.updateConstraints(item: self.view, closure: closure)
}
public func removeConstraints() {
ConstraintMaker.removeConstraints(item: self.view)
}
public var contentHuggingHorizontalPriority: Float {
get {
return self.view.contentHuggingPriority(for: .horizontal).rawValue
}
nonmutating set {
self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .horizontal)
}
}
public var contentHuggingVerticalPriority: Float {
get {
return self.view.contentHuggingPriority(for: .vertical).rawValue
}
nonmutating set {
self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .vertical)
}
}
public var contentCompressionResistanceHorizontalPriority: Float {
get {
return self.view.contentCompressionResistancePriority(for: .horizontal).rawValue
}
nonmutating set {
self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .horizontal)
}
}
public var contentCompressionResistanceVerticalPriority: Float {
get {
return self.view.contentCompressionResistancePriority(for: .vertical).rawValue
}
nonmutating set {
self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .vertical)
}
}
public var target: AnyObject? {
return self.view
}
internal let view: ConstraintView
internal init(view: ConstraintView) {
self.view = view
}
}
+169
View File
@@ -0,0 +1,169 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public extension LayoutConstraint {
override var description: String {
var description = "<"
description += descriptionForObject(self)
if let firstItem = conditionalOptional(from: self.firstItem) {
description += " \(descriptionForObject(firstItem))"
}
if self.firstAttribute != .notAnAttribute {
description += ".\(descriptionForAttribute(self.firstAttribute))"
}
description += " \(descriptionForRelation(self.relation))"
if let secondItem = self.secondItem {
description += " \(descriptionForObject(secondItem))"
}
if self.secondAttribute != .notAnAttribute {
description += ".\(descriptionForAttribute(self.secondAttribute))"
}
if self.multiplier != 1.0 {
description += " * \(self.multiplier)"
}
if self.secondAttribute == .notAnAttribute {
description += " \(self.constant)"
} else {
if self.constant > 0.0 {
description += " + \(self.constant)"
} else if self.constant < 0.0 {
description += " - \(abs(self.constant))"
}
}
if self.priority.rawValue != 1000.0 {
description += " ^\(self.priority)"
}
description += ">"
return description
}
}
private func descriptionForRelation(_ relation: LayoutRelation) -> String {
switch relation {
case .equal: return "=="
case .greaterThanOrEqual: return ">="
case .lessThanOrEqual: return "<="
#if swift(>=5.0)
@unknown default: return "unknown"
#endif
}
}
private func descriptionForAttribute(_ attribute: LayoutAttribute) -> String {
#if canImport(UIKit)
switch attribute {
case .notAnAttribute: return "notAnAttribute"
case .top: return "top"
case .left: return "left"
case .bottom: return "bottom"
case .right: return "right"
case .leading: return "leading"
case .trailing: return "trailing"
case .width: return "width"
case .height: return "height"
case .centerX: return "centerX"
case .centerY: return "centerY"
case .lastBaseline: return "lastBaseline"
case .firstBaseline: return "firstBaseline"
case .topMargin: return "topMargin"
case .leftMargin: return "leftMargin"
case .bottomMargin: return "bottomMargin"
case .rightMargin: return "rightMargin"
case .leadingMargin: return "leadingMargin"
case .trailingMargin: return "trailingMargin"
case .centerXWithinMargins: return "centerXWithinMargins"
case .centerYWithinMargins: return "centerYWithinMargins"
#if swift(>=5.0)
@unknown default: return "unknown"
#endif
}
#else
switch attribute {
case .notAnAttribute: return "notAnAttribute"
case .top: return "top"
case .left: return "left"
case .bottom: return "bottom"
case .right: return "right"
case .leading: return "leading"
case .trailing: return "trailing"
case .width: return "width"
case .height: return "height"
case .centerX: return "centerX"
case .centerY: return "centerY"
case .lastBaseline: return "lastBaseline"
case .firstBaseline: return "firstBaseline"
#if swift(>=5.0)
@unknown default: return "unknown"
#endif
}
#endif
}
private func conditionalOptional<T>(from object: Optional<T>) -> Optional<T> {
return object
}
private func conditionalOptional<T>(from object: T) -> Optional<T> {
return Optional.some(object)
}
private func descriptionForObject(_ object: AnyObject) -> String {
let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object)))
var desc = ""
desc += type(of: object).description()
if let object = object as? ConstraintView {
desc += ":\(object.snp.label() ?? pointerDescription)"
} else if let object = object as? LayoutConstraint {
desc += ":\(object.label ?? pointerDescription)"
} else {
desc += ":\(pointerDescription)"
}
if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 {
desc += "@\((file as NSString).lastPathComponent)#\(line)"
}
desc += ""
return desc
}
+61
View File
@@ -0,0 +1,61 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public class LayoutConstraint : NSLayoutConstraint {
public var label: String? {
get {
return self.identifier
}
set {
self.identifier = newValue
}
}
internal weak var constraint: Constraint? = nil
}
internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool {
// If firstItem or secondItem on either constraint has a dangling pointer
// this comparison can cause a crash. The solution for this is to ensure
// your layout code hold strong references to things like Views, LayoutGuides
// and LayoutAnchors as SnapKit will not keep strong references to any of these.
guard lhs.firstAttribute == rhs.firstAttribute &&
lhs.secondAttribute == rhs.secondAttribute &&
lhs.relation == rhs.relation &&
lhs.priority == rhs.priority &&
lhs.multiplier == rhs.multiplier &&
lhs.secondItem === rhs.secondItem &&
lhs.firstItem === rhs.firstItem else {
return false
}
return true
}
@@ -0,0 +1,93 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif
public protocol LayoutConstraintItem: AnyObject {
}
@available(iOS 9.0, OSX 10.11, *)
extension ConstraintLayoutGuide : LayoutConstraintItem {
}
extension ConstraintView : LayoutConstraintItem {
}
extension LayoutConstraintItem {
internal func prepare() {
if let view = self as? ConstraintView {
view.translatesAutoresizingMaskIntoConstraints = false
}
}
internal var superview: ConstraintView? {
if let view = self as? ConstraintView {
return view.superview
}
if #available(iOS 9.0, OSX 10.11, *), let guide = self as? ConstraintLayoutGuide {
return guide.owningView
}
return nil
}
internal var constraints: [Constraint] {
return self.constraintsSet.allObjects as! [Constraint]
}
internal func add(constraints: [Constraint]) {
let constraintsSet = self.constraintsSet
for constraint in constraints {
constraintsSet.add(constraint)
}
}
internal func remove(constraints: [Constraint]) {
let constraintsSet = self.constraintsSet
for constraint in constraints {
constraintsSet.remove(constraint)
}
}
private var constraintsSet: NSMutableSet {
let constraintsSet: NSMutableSet
if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSMutableSet {
constraintsSet = existing
} else {
constraintsSet = NSMutableSet()
objc_setAssociatedObject(self, &constraintsKey, constraintsSet, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return constraintsSet
}
}
private var constraintsKey: UInt8 = 0
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTrackingDomains</key>
<array/>
</dict>
</plist>
+42
View File
@@ -0,0 +1,42 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
#if canImport(UIKit)
import UIKit
#if swift(>=4.2)
typealias LayoutRelation = NSLayoutConstraint.Relation
typealias LayoutAttribute = NSLayoutConstraint.Attribute
#else
typealias LayoutRelation = NSLayoutRelation
typealias LayoutAttribute = NSLayoutAttribute
#endif
typealias LayoutPriority = UILayoutPriority
#else
import AppKit
typealias LayoutRelation = NSLayoutConstraint.Relation
typealias LayoutAttribute = NSLayoutConstraint.Attribute
typealias LayoutPriority = NSLayoutConstraint.Priority
#endif
@@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if canImport(UIKit)
import UIKit
#endif
@available(iOS 8.0, *)
public extension ConstraintLayoutSupport {
var snp: ConstraintLayoutSupportDSL {
return ConstraintLayoutSupportDSL(support: self)
}
}
@@ -53,6 +53,29 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## SnapKit
Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
## ZIPFoundation ## ZIPFoundation
MIT License MIT License
@@ -76,6 +76,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<key>Type</key> <key>Type</key>
<string>PSGroupSpecifier</string> <string>PSGroupSpecifier</string>
</dict> </dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>SnapKit</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict> <dict>
<key>FooterText</key> <key>FooterText</key>
<string>MIT License <string>MIT License
@@ -1,5 +1,7 @@
${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks.sh ${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks.sh
${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework ${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework
${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework ${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework
${BUILT_PRODUCTS_DIR}/RDReaderView/RDReaderView.framework ${BUILT_PRODUCTS_DIR}/RDEpubReaderView/RDEpubReaderView.framework
${BUILT_PRODUCTS_DIR}/RDPDFReaderView/RDPDFReaderView.framework
${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework ${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework
@@ -1,4 +1,6 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTCoreText.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTCoreText.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTFoundation.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTFoundation.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDReaderView.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDEpubReaderView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDPDFReaderView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework
@@ -1,5 +1,7 @@
${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks.sh ${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks.sh
${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework ${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework
${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework ${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework
${BUILT_PRODUCTS_DIR}/RDReaderView/RDReaderView.framework ${BUILT_PRODUCTS_DIR}/RDEpubReaderView/RDEpubReaderView.framework
${BUILT_PRODUCTS_DIR}/RDPDFReaderView/RDPDFReaderView.framework
${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework ${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework
@@ -1,4 +1,6 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTCoreText.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTCoreText.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTFoundation.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTFoundation.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDReaderView.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDEpubReaderView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RDPDFReaderView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework
@@ -178,13 +178,17 @@ code_sign_if_enabled() {
if [[ "$CONFIGURATION" == "Debug" ]]; then if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework" install_framework "${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework"
install_framework "${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework" install_framework "${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RDReaderView/RDReaderView.framework" install_framework "${BUILT_PRODUCTS_DIR}/RDEpubReaderView/RDEpubReaderView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RDPDFReaderView/RDPDFReaderView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework"
install_framework "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework" install_framework "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework"
fi fi
if [[ "$CONFIGURATION" == "Release" ]]; then if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework" install_framework "${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework"
install_framework "${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework" install_framework "${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RDReaderView/RDReaderView.framework" install_framework "${BUILT_PRODUCTS_DIR}/RDEpubReaderView/RDEpubReaderView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RDPDFReaderView/RDPDFReaderView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework"
install_framework "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework" install_framework "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework"
fi fi
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
@@ -0,0 +1,2 @@
${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-resources.sh
${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderViewAssets.bundle
@@ -0,0 +1 @@
${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RDEpubReaderViewAssets.bundle
@@ -0,0 +1,2 @@
${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-resources.sh
${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderViewAssets.bundle
@@ -0,0 +1 @@
${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RDEpubReaderViewAssets.bundle
@@ -0,0 +1,129 @@
#!/bin/sh
set -e
set -u
set -o pipefail
function on_error {
echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
}
trap 'on_error $LINENO' ERR
if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then
# If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy
# resources to, so exit 0 (signalling the script phase was successful).
exit 0
fi
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=()
# This protects against multiple targets copying the same framework dependency at the same time. The solution
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
case "${TARGETED_DEVICE_FAMILY:-}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
3)
TARGET_DEVICE_ARGS="--target-device tv"
;;
4)
TARGET_DEVICE_ARGS="--target-device watch"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
install_resource()
{
if [[ "$1" = /* ]] ; then
RESOURCE_PATH="$1"
else
RESOURCE_PATH="${PODS_ROOT}/$1"
fi
if [[ ! -e "$RESOURCE_PATH" ]] ; then
cat << EOM
error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
EOM
exit 1
fi
case $RESOURCE_PATH in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.framework)
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
echo "$RESOURCE_PATH" || true
echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
;;
esac
}
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_resource "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderViewAssets.bundle"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_resource "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderViewAssets.bundle"
fi
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find -L "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
else
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
fi
fi
@@ -1,12 +1,12 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView/RDReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2" HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView/RDPDFReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"xml2" -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "RDReaderView" -framework "ZIPFoundation" OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "PDFKit" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
@@ -1,12 +1,12 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView/RDReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2" HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView/RDPDFReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"xml2" -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "RDReaderView" -framework "ZIPFoundation" OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "PDFKit" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.0.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_RDEpubReaderView : NSObject
@end
@implementation PodsDummy_RDEpubReaderView
@end
@@ -0,0 +1,16 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
FOUNDATION_EXPORT double RDEpubReaderViewVersionNumber;
FOUNDATION_EXPORT const unsigned char RDEpubReaderViewVersionString[];
@@ -1,15 +1,15 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "ZIPFoundation" OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "SnapKit" -framework "ZIPFoundation"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT} PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../Sources/RDEpubReaderView
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES SKIP_INSTALL = YES
@@ -0,0 +1,6 @@
framework module RDEpubReaderView {
umbrella header "RDEpubReaderView-umbrella.h"
export *
module * { export * }
}
@@ -1,15 +1,15 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDReaderView CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "ZIPFoundation" OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "DTCoreText" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "SnapKit" -framework "ZIPFoundation"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT} PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../Sources/RDEpubReaderView
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES SKIP_INSTALL = YES
@@ -13,7 +13,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>BNDL</string> <string>BNDL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.0.1</string> <string>0.0.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
@@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_RDPDFReaderView : NSObject
@end
@implementation PodsDummy_RDPDFReaderView
@end
@@ -0,0 +1,12 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
@@ -0,0 +1,16 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
FOUNDATION_EXPORT double RDPDFReaderViewVersionNumber;
FOUNDATION_EXPORT const unsigned char RDPDFReaderViewVersionString[];
@@ -0,0 +1,16 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "PDFKit" -framework "SnapKit" -framework "Vision"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../Sources/RDPDFReaderView
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
@@ -0,0 +1,6 @@
framework module RDPDFReaderView {
umbrella header "RDPDFReaderView-umbrella.h"
export *
module * { export * }
}
@@ -0,0 +1,16 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "PDFKit" -framework "SnapKit" -framework "Vision"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../Sources/RDPDFReaderView
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
@@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_RDReaderView : NSObject
@end
@implementation PodsDummy_RDReaderView
@end
@@ -1,6 +0,0 @@
framework module RDReaderView {
umbrella header "RDReaderView-umbrella.h"
export *
module * { export * }
}
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>5.7.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More