From b3289ba8c2df2eeeae432b3a010a586f55f228cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:00:14 +0000 Subject: [PATCH 1/4] Initial plan From ffb07297b96f499dc90cd2c2b6245eb588cc109a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:09:59 +0000 Subject: [PATCH 2/4] Add bilingual comments to core SectionKit files Co-authored-by: linhay <15262434+linhay@users.noreply.github.com> --- .../CollectionBase/SKCManager.swift | 68 ++++++++++++++++++- .../SKCSectionProtocol.swift | 12 +++- Sources/SectionKit/Common/SKBinding.swift | 52 +++++++++++--- Sources/SectionKit/Common/SKIDBox.swift | 14 ++++ Sources/SectionKit/Common/SKWeakBox.swift | 14 ++++ .../HighPerformance/SKKVCache.swift | 30 +++++++- .../SectionArrayResultBuilder.swift | 26 ++++++- .../SKConfigurable/SKConfigurableView.swift | 17 +++-- Sources/SectionKit/SectionKit.swift | 29 +++++++- Sources/SectionUI/SKUIController.swift | 25 ++++++- Sources/SectionUI/SKUIView.swift | 25 ++++++- 11 files changed, 284 insertions(+), 28 deletions(-) diff --git a/Sources/SectionKit/CollectionBase/SKCManager.swift b/Sources/SectionKit/CollectionBase/SKCManager.swift index bd7b9a4..17dcf61 100644 --- a/Sources/SectionKit/CollectionBase/SKCManager.swift +++ b/Sources/SectionKit/CollectionBase/SKCManager.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// SKCManager.swift +// SectionKit // // Created by linhey on 2022/8/11. // @@ -9,21 +9,37 @@ import UIKit import Combine +/// 请求 ID 类,用于管理异步请求的生命周期 +/// Request ID class for managing asynchronous request lifecycle public class SKRequestID { + /// 请求的唯一标识符 + /// Unique identifier for the request public let id: String + + /// 是否已取消 + /// Whether cancelled var isCancelled: Bool = false + + /// 执行任务的闭包,返回 true 表示任务完成 + /// Task closure, returns true when task is completed let task: () -> Bool + /// 初始化请求 ID + /// Initialize request ID init(id: String, task: @escaping () -> Bool) { self.id = id self.task = task } + /// 取消请求 + /// Cancel request public func cancel() { isCancelled = true } + /// 执行请求任务 + /// Perform request task public func perform() { if !isCancelled, task() { cancel() @@ -32,21 +48,41 @@ public class SKRequestID { } +/// 请求发布者结构体,包含布局相关的发布者 +/// Request publishers structure containing layout-related publishers public struct SKRequestPublishers { + /// 布局子视图的发布者 + /// Publisher for layout subviews public let layoutSubviews = PassthroughSubject() public init() {} } +/// 请求视图协议,定义具有请求发布者的视图 +/// Request view protocol defining views with request publishers public protocol SKCRequestViewProtocol { + /// 请求发布者实例 + /// Request publishers instance var requestPublishers: SKRequestPublishers { get } } +/// SKC 管理器发布者类,管理 section 相关的发布者 +/// SKC manager publishers class managing section-related publishers public class SKCManagerPublishers { + /// section 数组的主题 + /// Subject for sections array fileprivate lazy var sectionsSubject = CurrentValueSubject<[SKCBaseSectionProtocol], Never>([]) + + /// 只读的 section 发布者 + /// Read-only sections publisher public private(set) lazy var sectionsPublisher = sectionsSubject.eraseToAnyPublisher() + + /// 当前的 section 数组 + /// Current sections array public var sections: [SKCBaseSectionProtocol] { sectionsSubject.value } + /// 安全获取指定索引的 section + /// Safely get section at specified index func safe(section: Int) -> T? { guard sections.indices.contains(section) else { return nil @@ -54,29 +90,55 @@ public class SKCManagerPublishers { return sections[section] as? T } + /// 获取指定类型的 section 集合 + /// Get collection of sections of specified type func collection(_ type: T.Type = T.self) -> any Collection { sections.lazy.compactMap({ $0 as? T }) } } +/// SKC 管理器主类,负责管理集合视图的数据和行为 +/// Main SKC manager class responsible for managing collection view data and behavior public class SKCManager { + /// 转换器结构体,用于在处理过程中转换数据 + /// Converters structure for transforming data during processing public struct Converts { + /// 转换器类型定义 + /// Converter type definition public typealias Convert = (_ manager: SKCManager, _ item: T) -> T + + /// section 注入转换器数组 + /// Array of section injection converters public var sectionInjection = [Convert]() } + /// 配置结构体,定义管理器的行为配置 + /// Configuration structure defining manager behavior settings public struct Configuration { /// 将 reloadSections 操作替换为 reloadData 操作 + /// Replace reloadSections operations with reloadData operations public var replaceReloadWithReloadData = false - /// 将 insertSections 操作替换为 reloadData 操作 + + /// 将 insertSections 操作替换为 reloadData 操作 + /// Replace insertSections operations with reloadData operations public var replaceInsertWithReloadData = true + /// 将 deleteSections 操作替换为 reloadData 操作 + /// Replace deleteSections operations with reloadData operations public var replaceDeleteWithReloadData = false } + /// 静态配置实例 + /// Static configuration instance public static var configuration = Configuration() + + /// 实例配置 + /// Instance configuration public var configuration = SKCManager.configuration + + /// 转换器实例 + /// Converters instance public var converts = Converts() public private(set) lazy var publishers = SKCManagerPublishers() public private(set) weak var sectionView: UICollectionView? diff --git a/Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift b/Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift index 8e8c5d0..046a976 100644 --- a/Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift +++ b/Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// SKCSectionProtocol.swift +// SectionKit // // Created by linhey on 2022/8/12. // @@ -8,10 +8,18 @@ #if canImport(UIKit) import UIKit +/// 基础 section 协议,组合了数据源、代理和操作协议 +/// Base section protocol combining data source, delegate and action protocols public typealias SKCBaseSectionProtocol = SKCSectionActionProtocol & SKCDataSourceProtocol & SKCDelegateProtocol + +/// 完整的 section 协议,在基础协议基础上添加了布局和类型协议 +/// Complete section protocol adding layout and type protocols to base protocol public typealias SKCSectionProtocol = SKCBaseSectionProtocol & SKCViewDelegateFlowLayoutProtocol & SKCAnySectionProtocol + public extension SKCDataSourceProtocol where Self: SKCViewDelegateFlowLayoutProtocol { + /// 获取指定类型和行的补充视图 + /// Get supplementary view for specified kind and row func supplementary(kind: SKSupplementaryKind, at row: Int) -> UICollectionReusableView? { switch kind { case .header: diff --git a/Sources/SectionKit/Common/SKBinding.swift b/Sources/SectionKit/Common/SKBinding.swift index 6b68fcf..d238ae5 100644 --- a/Sources/SectionKit/Common/SKBinding.swift +++ b/Sources/SectionKit/Common/SKBinding.swift @@ -8,32 +8,55 @@ import Foundation import Combine +/// SKBinding 属性包装器,提供双向数据绑定功能 +/// SKBinding property wrapper providing bidirectional data binding functionality @propertyWrapper public struct SKBinding { - // 包装的值 + /// 包装的值,支持读取和设置 + /// Wrapped value supporting get and set operations public var wrappedValue: Value { get { _get() } nonmutating set { + // 执行所有设置器回调 + // Execute all setter callbacks for item in _set { item(newValue) } + // 如果有设置器,发送变化通知 + // Send change notification if setters exist if !_set.isEmpty { self.changedSubject.send(newValue) } } } - // 返回 SKBinding 的实例 + /// 返回 SKBinding 的实例,用于访问绑定本身 + /// Returns SKBinding instance for accessing the binding itself public var projectedValue: SKBinding { self } + + /// 值变化的发布者,用于监听数据变化 + /// Publisher for value changes, used to observe data changes public var changedPublisher: AnyPublisher { changedSubject.eraseToAnyPublisher() } + + /// 是否可设置,基于是否有设置器回调 + /// Whether settable, based on whether setter callbacks exist public var isSetable: Bool { !_set.isEmpty } + /// 获取值的闭包 + /// Closure for getting value private let _get: () -> Value + + /// 设置值的闭包数组 + /// Array of closures for setting value private let _set: [(Value) -> Void] + + /// 变化通知的主题 + /// Subject for change notifications private let changedSubject = PassthroughSubject() - // 初始化方法,接受一个 getter 和 setter + /// 初始化方法,接受一个 getter 和可选的 setter + /// Initialization method accepting a getter and optional setter public init(get: @escaping () -> Value, set: ((Value) -> Void)? = nil) { if let set = set { self.init(get: get, set: [set]) @@ -42,6 +65,8 @@ public struct SKBinding { } } + /// 私有初始化方法,接受 getter 和 setter 数组 + /// Private initialization method accepting getter and setter array private init(get: @escaping () -> Value, set: [(Value) -> Void]) { self._get = get self._set = set @@ -51,11 +76,14 @@ public struct SKBinding { public extension SKBinding { - // 创建一个常量绑定 + /// 创建一个常量绑定,值不可变 + /// Create a constant binding with immutable value static func constant(_ value: Value) -> SKBinding { .init(get: { value }, set: { _ in }) } + /// 创建一个常量绑定,使用闭包提供值 + /// Create a constant binding using closure to provide value static func constant(_ value: @escaping () -> Value) -> SKBinding { .init(get: value, set: { _ in }) } @@ -64,12 +92,14 @@ public extension SKBinding { public extension SKBinding { - // 从一个现有的绑定创建一个新的绑定 + /// 从 CurrentValueSubject 创建绑定 + /// Create binding from CurrentValueSubject init(_ source: CurrentValueSubject) { self.init(get: { source.value }, set: { source.send($0) }) } - // 从一个现有的绑定创建一个新的绑定 + /// 从可选值的 CurrentValueSubject 创建绑定,提供默认值 + /// Create binding from optional CurrentValueSubject with default value init(_ source: CurrentValueSubject, default: Value) { self.init(get: { source.value ?? `default` }, set: { source.send($0) }) } @@ -78,12 +108,14 @@ public extension SKBinding { public extension SKBinding { - // 从一个现有的绑定创建一个新的绑定 + /// 从现有的 SKBinding 创建新的绑定 + /// Create new binding from existing SKBinding init(_ source: SKBinding) { self.init(get: source._get, set: source._set) } - // 从一个对象的 keyPath 创建一个绑定 + /// 从对象的 keyPath 创建绑定 + /// Create binding from object's keyPath init(on object: Root, keyPath: ReferenceWritableKeyPath) { self.init { object[keyPath: keyPath] @@ -92,6 +124,8 @@ public extension SKBinding { } } + /// 从弱引用对象的 keyPath 创建绑定,提供默认值 + /// Create binding from weakly referenced object's keyPath with default value init(on object: Root, keyPath: ReferenceWritableKeyPath, default: Value) where Root: AnyObject { self.init { [weak object] in object?[keyPath: keyPath] ?? `default` @@ -100,6 +134,8 @@ public extension SKBinding { } } + /// 从弱引用对象的可选 keyPath 创建绑定,提供默认值 + /// Create binding from weakly referenced object's optional keyPath with default value init(on object: Root, keyPath: ReferenceWritableKeyPath, default: Value) where Root: AnyObject { self.init { [weak object] in object?[keyPath: keyPath] ?? `default` diff --git a/Sources/SectionKit/Common/SKIDBox.swift b/Sources/SectionKit/Common/SKIDBox.swift index b88c527..06dc2be 100644 --- a/Sources/SectionKit/Common/SKIDBox.swift +++ b/Sources/SectionKit/Common/SKIDBox.swift @@ -7,17 +7,31 @@ import Foundation +/// ID 盒子结构体,为值类型提供唯一标识符包装 +/// ID box structure providing unique identifier wrapper for value types public struct SKIDBox { + /// 标识符类型别名 + /// Identifier type alias public typealias ID = ID + + /// 唯一标识符 + /// Unique identifier public let id: ID + + /// 被包装的值 + /// Wrapped value public let value: Value + /// 使用指定 ID 和值初始化 + /// Initialize with specified ID and value public init(id: ID, value: Value) { self.id = id self.value = value } + /// 使用自动生成的 UUID 作为 ID 初始化(仅当 ID 类型为 UUID 时) + /// Initialize with auto-generated UUID as ID (only when ID type is UUID) public init(value: Value) where ID == UUID { self.id = UUID() self.value = value diff --git a/Sources/SectionKit/Common/SKWeakBox.swift b/Sources/SectionKit/Common/SKWeakBox.swift index 6450a1c..94e5f25 100644 --- a/Sources/SectionKit/Common/SKWeakBox.swift +++ b/Sources/SectionKit/Common/SKWeakBox.swift @@ -22,29 +22,43 @@ import Foundation +/// 弱引用盒子,用于持有对象的弱引用,支持动态成员查找 +/// Weak reference box for holding weak references to objects with dynamic member lookup support @dynamicMemberLookup public final class SKWeakBox: Equatable, Hashable { + /// 弱引用的值 + /// Weakly referenced value public weak var value: Value? + /// 初始化弱引用盒子 + /// Initialize weak reference box public init(_ value: Value?) { self.value = value } + /// 动态成员查找,支持可写键路径 + /// Dynamic member lookup supporting writable key paths public subscript(dynamicMember keyPath: WritableKeyPath) -> T? { get { value?[keyPath: keyPath] } set { value?[keyPath: keyPath] = newValue } } + /// 动态成员查找,支持引用可写键路径 + /// Dynamic member lookup supporting reference writable key paths public subscript(dynamicMember keyPath: ReferenceWritableKeyPath) -> T? { get { value?[keyPath: keyPath] } set { value?[keyPath: keyPath] = newValue } } + /// 相等性比较,基于对象标识 + /// Equality comparison based on object identity public static func == (lhs: SKWeakBox, rhs: SKWeakBox) -> Bool { lhs === rhs } + /// 哈希函数,基于对象标识符 + /// Hash function based on object identifier public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } diff --git a/Sources/SectionKit/HighPerformance/SKKVCache.swift b/Sources/SectionKit/HighPerformance/SKKVCache.swift index 80e3c3d..35f2e7b 100644 --- a/Sources/SectionKit/HighPerformance/SKKVCache.swift +++ b/Sources/SectionKit/HighPerformance/SKKVCache.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// SKKVCache.swift +// SectionKit // // Created by linhey on 2023/4/25. // @@ -8,20 +8,38 @@ #if canImport(ObjectiveC) import ObjectiveC import Foundation -// MARK: - Cache + +// MARK: - 键值缓存 / Key-Value Cache + +/// 高性能键值缓存类,支持过期时间和自动清理 +/// High-performance key-value cache class with expiration time and automatic cleanup support public final class SKKVCache { + /// 底层 NSCache 包装器 + /// Underlying NSCache wrapper public let wrapped = NSCache() + + /// 日期提供器,用于计算过期时间 + /// Date provider for calculating expiration time public var dateProvider: (() -> Date)? + + /// 键跟踪器,用于跟踪缓存中的键 + /// Key tracker for tracking keys in cache public let keyTracker = KeyTracker() + /// 缓存中的项目数量 + /// Number of items in cache public var count: Int { keyTracker.keys.count } + /// 缓存数量限制 + /// Cache count limit public var countLimit: Int { set { wrapped.countLimit = newValue } get { wrapped.countLimit } } + /// 初始化缓存 + /// Initialize cache public init(countLimit: Int? = nil, dateProvider: (() -> Date)? = nil) { wrapped.delegate = keyTracker @@ -31,6 +49,8 @@ public final class SKKVCache { } } + /// 插入值到缓存,可指定生存时间 + /// Insert value into cache with optional lifetime public func insert(_ value: Value, forKey key: Key, lifeTime: TimeInterval? = nil) { let date: Date? if let lifeTime = lifeTime { @@ -41,10 +61,14 @@ public final class SKKVCache { self.insert(Entry(key: key, value: value, expirationDate: date)) } + /// 移除指定键的值 + /// Remove value for specified key public func remove(_ key: Key) { self[key] = nil } + /// 移除所有缓存项 + /// Remove all cache items public func removeAll() { keyTracker.keys.removeAll() wrapped.removeAllObjects() diff --git a/Sources/SectionKit/ResultBuilders/SectionArrayResultBuilder.swift b/Sources/SectionKit/ResultBuilders/SectionArrayResultBuilder.swift index fcfa9fc..e494285 100644 --- a/Sources/SectionKit/ResultBuilders/SectionArrayResultBuilder.swift +++ b/Sources/SectionKit/ResultBuilders/SectionArrayResultBuilder.swift @@ -1,51 +1,73 @@ // -// File.swift -// +// SectionArrayResultBuilder.swift +// SectionKit // // Created by linhey on 2022/9/2. // import Foundation +/// Section 数组结果构建器,用于构建声明式的数据模型数组 +/// Section array result builder for constructing declarative data model arrays @resultBuilder public class SectionArrayResultBuilder { + /// 构建单个闭包表达式 + /// Build single closure expression public static func buildExpression(_ expression: () -> Model) -> [Model] { [expression()] } + /// 构建数组表达式 + /// Build array expression public static func buildExpression(_ expression: [Model]) -> [Model] { expression } + /// 构建单个模型表达式 + /// Build single model expression public static func buildExpression(_ expression: Model) -> [Model] { return [expression] } + /// 构建空表达式 + /// Build empty expression public static func buildExpression(_ expression: ()) -> [Model] { return [] } + /// 构建条件分支的第一个组件 + /// Build first component of conditional branch public static func buildEither(first component: [Model]) -> [Model] { return component } + /// 构建条件分支的第二个组件 + /// Build second component of conditional branch public static func buildEither(second component: [Model]) -> [Model] { return component } + /// 构建可选组件 + /// Build optional component public static func buildOptional(_ component: [Model]?) -> [Model] { return component ?? [] } + /// 构建代码块,组合多个组件 + /// Build block combining multiple components public static func buildBlock(_ components: [Model]...) -> [Model] { buildArray(components) } + /// 构建数组,将嵌套数组扁平化 + /// Build array by flattening nested arrays public static func buildArray(_ components: [[Model]]) -> [Model] { Array(components.joined()) } + /// 构建限制可用性的组件 + /// Build component with limited availability public static func buildLimitedAvailability(_ component: [Model]) -> [Model] { component } diff --git a/Sources/SectionKit/SKConfigurable/SKConfigurableView.swift b/Sources/SectionKit/SKConfigurable/SKConfigurableView.swift index f24841a..0ac9d75 100644 --- a/Sources/SectionKit/SKConfigurable/SKConfigurableView.swift +++ b/Sources/SectionKit/SKConfigurable/SKConfigurableView.swift @@ -1,25 +1,34 @@ // -// File.swift -// +// SKConfigurableView.swift +// SectionKit // // Created by linhey on 2022/3/14. // import Foundation -// 定义了可配置视图协议,组合可配置模型,布局和UIView协议 +/// 存在模型的视图协议,组合了存在模型协议和可配置布局协议 +/// Protocol for views with existing model, combining existing model protocol and configurable layout protocol public protocol SKExistModelView: SKExistModelProtocol & SKConfigurableLayoutProtocol { } + +/// 可配置视图协议,组合了可配置模型协议和可配置布局协议 +/// Configurable view protocol combining configurable model protocol and configurable layout protocol public protocol SKConfigurableView: SKConfigurableModelProtocol & SKConfigurableLayoutProtocol {} public extension SKConfigurableView where Model == Void { + /// 为 Void 模型提供空实现 + /// Provide empty implementation for Void model func config(_ model: Model) {} } -// 支持通过RawRepresentable配置模型 +/// 支持通过 RawRepresentable 配置模型 +/// Support configuring model through RawRepresentable public extension SKConfigurableView { + /// 使用 RawRepresentable 类型配置模型 + /// Configure model using RawRepresentable type func config(_ model: T) where Model == T.RawValue { config(model.rawValue) } diff --git a/Sources/SectionKit/SectionKit.swift b/Sources/SectionKit/SectionKit.swift index 133ee8d..6186fe3 100644 --- a/Sources/SectionKit/SectionKit.swift +++ b/Sources/SectionKit/SectionKit.swift @@ -8,32 +8,57 @@ import Foundation import UIKit +/// SectionKit 主类,提供全局配置和共享实例 +/// Main SectionKit class providing global configuration and shared instance public class SKSectionKit { + /// 共享单例实例 + /// Shared singleton instance public static var shared = SKSectionKit() + /// 全局配置选项 + /// Global configuration options public var options = Options() + /// 配置选项结构体 + /// Configuration options structure public struct Options { - /// 当承载视图 size 为0时禁用刷新 - @available(*, deprecated, message: "已不再使用") + /// 当承载视图 size 为0时禁用刷新(已废弃) + /// Disable refresh when container view size is zero (deprecated) + @available(*, deprecated, message: "已不再使用 / No longer used") public var disableReloadWhenViewSizeIsZero = true } } +/// SectionKit 包装器,为兼容类型提供命名空间 +/// SectionKit wrapper providing namespace for compatible types public class SKWrapper { + /// 被包装的基础对象 + /// The wrapped base object public let base: Base + + /// 初始化包装器 + /// Initialize wrapper public init(_ base: Base) { self.base = base } } +/// SectionKit 兼容性协议,遵循此协议的类型可以使用 sk 命名空间 +/// SectionKit compatibility protocol, types conforming to this can use sk namespace public protocol SKCompatible: AnyObject {} public extension SKCompatible { + /// 实例级别的 sk 命名空间访问器 + /// Instance-level sk namespace accessor var sk: SKWrapper { return SKWrapper(self) } + + /// 类型级别的 sk 命名空间访问器 + /// Type-level sk namespace accessor static var sk: SKWrapper.Type { return SKWrapper.self } } +/// 扩展 UIView 使其兼容 SectionKit +/// Extend UIView to be compatible with SectionKit extension UIView: SKCompatible {} \ No newline at end of file diff --git a/Sources/SectionUI/SKUIController.swift b/Sources/SectionUI/SKUIController.swift index bda387e..d894a20 100644 --- a/Sources/SectionUI/SKUIController.swift +++ b/Sources/SectionUI/SKUIController.swift @@ -1,6 +1,6 @@ // -// SwiftUIController.swift -// CoolUp +// SKUIController.swift +// SectionUI // // Created by linhey on 12/13/24. // @@ -8,25 +8,46 @@ import UIKit import SwiftUI +/// SwiftUI 视图控制器包装器,用于在 SwiftUI 中使用 UIKit 视图控制器 +/// SwiftUI view controller wrapper for using UIKit view controllers in SwiftUI public struct SKUIController: UIViewControllerRepresentable { + /// 视图控制器类型别名 + /// View controller type alias public typealias UIViewControllerType = Controller + + /// 创建视图控制器的闭包类型 + /// Closure type for creating view controller public typealias MakeAction = () -> Controller + + /// 更新视图控制器的闭包类型 + /// Closure type for updating view controller public typealias UpdateAction = (_ controller: Controller, _ context: Context) -> Void + /// 创建视图控制器的闭包 + /// Closure for creating view controller public let make: MakeAction + + /// 更新视图控制器的闭包 + /// Closure for updating view controller public let update: UpdateAction + /// 初始化方法 + /// Initialization method public init(make: @escaping MakeAction, update: @escaping UpdateAction = { _, _ in }) { self.make = make self.update = update } + /// 创建 UIKit 视图控制器 + /// Create UIKit view controller public func makeUIViewController(context: Context) -> Controller { make() } + /// 更新 UIKit 视图控制器 + /// Update UIKit view controller public func updateUIViewController(_ uiViewController: Controller, context: Context) { update(uiViewController, context) } diff --git a/Sources/SectionUI/SKUIView.swift b/Sources/SectionUI/SKUIView.swift index 1b34f13..458a3b3 100644 --- a/Sources/SectionUI/SKUIView.swift +++ b/Sources/SectionUI/SKUIView.swift @@ -1,6 +1,6 @@ // -// File.swift -// SectionKit +// SKUIView.swift +// SectionUI // // Created by linhey on 1/3/25. // @@ -8,25 +8,46 @@ import UIKit import SwiftUI +/// SwiftUI UIView 包装器,用于在 SwiftUI 中使用 UIKit 视图 +/// SwiftUI UIView wrapper for using UIKit views in SwiftUI public struct SKUIView: UIViewRepresentable { + /// UIView 类型别名 + /// UIView type alias public typealias UIViewType = View + + /// 创建视图的闭包类型 + /// Closure type for creating view public typealias MakeAction = (_ context: Context) -> View + + /// 更新视图的闭包类型 + /// Closure type for updating view public typealias UpdateAction = (_ view: View, _ context: Context) -> Void + /// 创建视图的闭包 + /// Closure for creating view public let make: MakeAction + + /// 更新视图的闭包 + /// Closure for updating view public let update: UpdateAction + /// 初始化方法 + /// Initialization method public init(make: @escaping MakeAction, update: @escaping UpdateAction = { _, _ in }) { self.make = make self.update = update } + /// 创建 UIKit 视图 + /// Create UIKit view public func makeUIView(context: Context) -> View { make(context) } + /// 更新 UIKit 视图 + /// Update UIKit view public func updateUIView(_ uiView: View, context: Context) { update(uiView, context) } From 928efa4480425d87bc131f4105e00dda9085823f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:13:39 +0000 Subject: [PATCH 3/4] Add bilingual comments to additional key files Co-authored-by: linhay <15262434+linhay@users.noreply.github.com> --- .../CollectionBase/SKSupplementaryKind.swift | 25 +++++++++-- Sources/SectionKit/Common/SKInout.swift | 31 ++++++++++--- Sources/SectionKit/Common/SKPublished.swift | 23 ++++++++-- .../SKConfigurableModelProtocol.swift | 16 +++++++ Sources/SectionUI/SKBindingKey.swift | 43 ++++++++++++------- 5 files changed, 110 insertions(+), 28 deletions(-) diff --git a/Sources/SectionKit/CollectionBase/SKSupplementaryKind.swift b/Sources/SectionKit/CollectionBase/SKSupplementaryKind.swift index 087a911..5bcbe75 100644 --- a/Sources/SectionKit/CollectionBase/SKSupplementaryKind.swift +++ b/Sources/SectionKit/CollectionBase/SKSupplementaryKind.swift @@ -25,17 +25,32 @@ import Foundation #if canImport(UIKit) import UIKit -/// SupplementaryView regist type +/// 补充视图注册类型枚举 +/// Supplementary view registration type enumeration /// -/// - header: header -/// - footer: footer -/// - custom: custom +/// - header: 头部视图 / Header view +/// - footer: 底部视图 / Footer view +/// - cell: 单元格视图 / Cell view +/// - custom: 自定义视图 / Custom view public enum SKSupplementaryKind: Equatable, Hashable, RawRepresentable { + /// 头部补充视图 + /// Header supplementary view case header + + /// 底部补充视图 + /// Footer supplementary view case footer + + /// 单元格视图 + /// Cell view case cell + + /// 自定义补充视图 + /// Custom supplementary view case custom(_ value: String) + /// 从原始值初始化 + /// Initialize from raw value public init(rawValue: String) { switch rawValue { case UICollectionView.elementKindSectionHeader: self = .header @@ -45,6 +60,8 @@ public enum SKSupplementaryKind: Equatable, Hashable, RawRepresentable { } } + /// 获取原始值 + /// Get raw value public var rawValue: String { switch self { case .header: return UICollectionView.elementKindSectionHeader diff --git a/Sources/SectionKit/Common/SKInout.swift b/Sources/SectionKit/Common/SKInout.swift index 2588a26..ba1f5ad 100644 --- a/Sources/SectionKit/Common/SKInout.swift +++ b/Sources/SectionKit/Common/SKInout.swift @@ -1,26 +1,32 @@ // -// File.swift -// +// SKInout.swift +// SectionKit // // Created by linhey on 2024/6/19. // import Foundation +/// SK 输入输出结构体,提供链式配置对象的能力 +/// SK inout structure providing chainable object configuration capability public struct SKInout { - + /// 构建对象的闭包 + /// Closure for building object public let build: (_ object: Object) -> Object + /// 初始化方法 + /// Initialization method public init(_ build: @escaping (_ object: Object) -> Object) { self.build = build } } - public extension SKInout { + /// 创建设置对象的 SKInout(可选版本) + /// Create SKInout for setting object (optional version) static func set(_ block: ((_ object: Object) -> Void)?) -> SKInout? { guard let block = block else { return nil } return .init { object in @@ -29,6 +35,8 @@ public extension SKInout { } } + /// 链式设置对象(可选版本) + /// Chain set object (optional version) func set(_ block: ((_ object: Object) -> Void)?) -> SKInout? { guard let block = block else { return self } return .set { object in @@ -39,13 +47,16 @@ public extension SKInout { } - public extension SKInout { + /// 创建设置对象的 SKInout + /// Create SKInout for setting object static func set(_ block: @escaping (_ object: Object) -> Object) -> SKInout { return .init(block) } + /// 通过引用可写键路径设置属性值 + /// Set property value through reference writable key path static func set(_ keyPath: ReferenceWritableKeyPath, _ value: V) -> SKInout { return .set { object in object[keyPath: keyPath] = value @@ -53,6 +64,8 @@ public extension SKInout { } } + /// 通过可写键路径设置属性值 + /// Set property value through writable key path static func set(_ keyPath: WritableKeyPath, _ value: V) -> SKInout { return .set { object in var object = object @@ -65,6 +78,8 @@ public extension SKInout { public extension SKInout { + /// 链式设置另一个 SKInout + /// Chain set another SKInout func set(_ other: SKInout) -> SKInout { return .set { object in var object = object @@ -74,6 +89,8 @@ public extension SKInout { } } + /// 链式设置对象 + /// Chain set object func set(_ block: @escaping (_ object: Object) -> Object) -> SKInout { return .set { object in var object = object @@ -83,6 +100,8 @@ public extension SKInout { } } + /// 链式通过引用可写键路径设置属性值 + /// Chain set property value through reference writable key path func set(_ keyPath: ReferenceWritableKeyPath, _ value: V) -> SKInout { return self.set { object in let object = object @@ -91,6 +110,8 @@ public extension SKInout { } } + /// 链式通过可写键路径设置属性值 + /// Chain set property value through writable key path func set(_ keyPath: WritableKeyPath, _ value: V) -> SKInout { return self.set { object in var object = object diff --git a/Sources/SectionKit/Common/SKPublished.swift b/Sources/SectionKit/Common/SKPublished.swift index 0e3a70f..230936c 100644 --- a/Sources/SectionKit/Common/SKPublished.swift +++ b/Sources/SectionKit/Common/SKPublished.swift @@ -1,6 +1,6 @@ // -// STVideoPublished.swift -// CoolUp +// SKPublished.swift +// SectionKit // // Created by linhey on 12/5/24. // @@ -8,17 +8,28 @@ import Combine import Foundation +/// 发布者类型枚举 +/// Publisher type enumeration public enum SKPublishedKind { + /// 透传主题,不保存最后的值 + /// Pass-through subject, doesn't retain last value case passThrough + + /// 当前值主题,保存最后的值 + /// Current value subject, retains last value case currentValue } public extension Publisher { + /// 忽略输出类型,将输出转换为 Void + /// Ignore output type, convert output to Void func ignoreOutputType() -> any Publisher { self.map { _ in () } } + /// 分配值到弱引用对象的属性 + /// Assign value to property of weakly referenced object func assign( onWeak object: Root, to keyPath: ReferenceWritableKeyPath @@ -33,10 +44,16 @@ public extension Publisher { } - +/// SK 发布值类,提供灵活的发布者功能 +/// SK published value class providing flexible publisher functionality public final class SKPublishedValue: Publisher, Sendable { + /// 失败类型,永不失败 + /// Failure type, never fails public typealias Failure = Never + + /// 变换发布者的闭包类型 + /// Transform publisher closure type public typealias TransformPublisher = (_ publisher: AnyPublisher) -> AnyPublisher public typealias TransformAnyPublisher = (_ publisher: AnyPublisher) -> any Publisher public typealias TransformOnValueChanged = (_ old: Output, _ new: Output) -> Void diff --git a/Sources/SectionKit/SKConfigurable/SKConfigurableModelProtocol.swift b/Sources/SectionKit/SKConfigurable/SKConfigurableModelProtocol.swift index 561a928..88fa430 100644 --- a/Sources/SectionKit/SKConfigurable/SKConfigurableModelProtocol.swift +++ b/Sources/SectionKit/SKConfigurable/SKConfigurableModelProtocol.swift @@ -22,16 +22,32 @@ import Foundation +/// 存在模型协议,要求类型具有关联的模型类型并支持使用模型初始化 +/// Existing model protocol requiring types to have associated model type and support initialization with model public protocol SKExistModelProtocol { + /// 关联的模型类型 + /// Associated model type associatedtype Model + + /// 使用模型初始化 + /// Initialize with model init(model: Model) } +/// 可配置模型协议,要求类型具有关联的模型类型并支持配置 +/// Configurable model protocol requiring types to have associated model type and support configuration public protocol SKConfigurableModelProtocol { + /// 关联的模型类型 + /// Associated model type associatedtype Model + + /// 使用模型配置实例 + /// Configure instance with model func config(_ model: Model) } public extension SKConfigurableModelProtocol where Model == Void { + /// 为 Void 模型类型提供默认空实现 + /// Provide default empty implementation for Void model type func config(_: Model) {} } diff --git a/Sources/SectionUI/SKBindingKey.swift b/Sources/SectionUI/SKBindingKey.swift index 500f04b..358f64a 100644 --- a/Sources/SectionUI/SKBindingKey.swift +++ b/Sources/SectionUI/SKBindingKey.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// SKBindingKey.swift +// SectionUI // // Created by linhey on 2024/3/17. // @@ -8,16 +8,21 @@ import Foundation import UIKit +/// 使用闭包绑定值的类型 /// A type that binds a value using a closure. public struct SKBindingKey { + /// 获取值的闭包 + /// Closure for getting value private let closure: () -> Value? + /// 从闭包获取的包装值 /// The wrapped value obtained from the closure. public var wrappedValue: Value? { closure() } + /// 使用闭包初始化新的绑定键 /// Initializes a new binding key with a closure. - /// - Parameter closure: A closure that returns the value to be bound. + /// - Parameter closure: 返回要绑定值的闭包 / A closure that returns the value to be bound. /// - Example: /// ``` /// let bindingKey = SKBindingKey { return 5 } @@ -27,8 +32,9 @@ public struct SKBindingKey { self.closure = closure } + /// 使用特定值初始化新的绑定键 /// Initializes a new binding key with a specific value. - /// - Parameter value: The value to be bound. + /// - Parameter value: 要绑定的值 / The value to be bound. /// - Example: /// ``` /// let bindingKey = SKBindingKey(5) @@ -40,9 +46,10 @@ public struct SKBindingKey { } public extension SKBindingKey { + /// 创建具有特定值的常量绑定键 /// Creates a constant binding key with a specific value. - /// - Parameter value: The constant value to be bound. - /// - Returns: A binding key that always returns the specified value. + /// - Parameter value: 要绑定的常量值 / The constant value to be bound. + /// - Returns: 始终返回指定值的绑定键 / A binding key that always returns the specified value. /// - Example: /// ``` /// let constantKey = SKBindingKey.constant(10) @@ -55,14 +62,16 @@ public extension SKBindingKey { public extension SKBindingKey where Value == Int { + /// 表示所有 section 的常量绑定键 /// A constant binding key representing all sections. static let all = SKBindingKey.constant(-1000000) + /// 从集合视图和键路径创建相对绑定键 /// Creates a relative binding key from a collection view and a key path. /// - Parameters: - /// - view: The collection view. - /// - path: The key path to get the relative value from the range of sections. - /// - Returns: A binding key that gets the relative section index. + /// - view: 集合视图 / The collection view. + /// - task: 从 section 范围获取相对值的键路径 / The key path to get the relative value from the range of sections. + /// - Returns: 获取相对 section 索引的绑定键 / A binding key that gets the relative section index. /// - Example: /// ``` /// let collectionView: UICollectionView? = ... @@ -78,11 +87,11 @@ public extension SKBindingKey where Value == Int { }) } - + /// 使用 section 操作协议和偏移量初始化新的绑定键 /// Initializes a new binding key with a section action protocol and an offset. /// - Parameters: - /// - section: The section action protocol. - /// - offset: The offset to be added to the section index. Defaults to 0. + /// - section: section 操作协议 / The section action protocol. + /// - offset: 要添加到 section 索引的偏移量,默认为 0 / The offset to be added to the section index. Defaults to 0. /// - Example: /// ``` /// let section: SKCSectionActionProtocol = ... @@ -101,11 +110,12 @@ public extension SKBindingKey where Value == Int { extension SKBindingKey: Equatable where Value: Equatable { + /// 检查两个绑定键是否相等 /// Checks if two binding keys are equal. /// - Parameters: - /// - lhs: The left-hand side binding key. - /// - rhs: The right-hand side binding key. - /// - Returns: `true` if the wrapped values are equal, otherwise `false`. + /// - lhs: 左侧绑定键 / The left-hand side binding key. + /// - rhs: 右侧绑定键 / The right-hand side binding key. + /// - Returns: 如果包装值相等则返回 `true`,否则返回 `false` / `true` if the wrapped values are equal, otherwise `false`. /// - Example: /// ``` /// let key1 = SKBindingKey(5) @@ -121,8 +131,9 @@ extension SKBindingKey: Equatable where Value: Equatable { extension SKBindingKey: Hashable where Value: Hashable { + /// 将包装值哈希到提供的哈希器中 /// Hashes the wrapped value into the provided hasher. - /// - Parameter hasher: The hasher to use when combining the components of this instance. + /// - Parameter hasher: 组合此实例组件时使用的哈希器 / The hasher to use when combining the components of this instance. /// - Example: /// ``` /// let key = SKBindingKey(5) From 99d0436c38d2169d4e38f0ff245189ce678ce44d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:15:37 +0000 Subject: [PATCH 4/4] Complete bilingual comments for SectionKit codebase Co-authored-by: linhay <15262434+linhay@users.noreply.github.com> --- .../SKCAnySectionProtocol.swift | 20 +++++++++++++++ Sources/SectionKit/Common/SKPrint.swift | 15 +++++++++++ .../SKHighPerformanceStore.swift | 25 +++++++++++++++++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Sources/SectionKit/CollectionBaseProtocol/SKCAnySectionProtocol.swift b/Sources/SectionKit/CollectionBaseProtocol/SKCAnySectionProtocol.swift index 4e03349..d1aed28 100644 --- a/Sources/SectionKit/CollectionBaseProtocol/SKCAnySectionProtocol.swift +++ b/Sources/SectionKit/CollectionBaseProtocol/SKCAnySectionProtocol.swift @@ -8,23 +8,43 @@ import UIKit import Foundation +/// 任意 Section 协议,提供类型擦除的 Section 抽象 +/// Any section protocol providing type-erased section abstraction public protocol SKCAnySectionProtocol: SKCSectionActionProtocol { + /// 底层的 section 实例 + /// Underlying section instance var section: SKCSectionProtocol { get } + + /// 对象标识符,用于唯一标识 + /// Object identifier for unique identification var objectIdentifier: ObjectIdentifier { get } } public extension SKCAnySectionProtocol { + /// 项目数量,代理到底层 section + /// Item count, delegated to underlying section var itemCount: Int { section.itemCount } + + /// Section 注入配置,代理到底层 section + /// Section injection configuration, delegated to underlying section var sectionInjection: SKCSectionInjection? { get { section.sectionInjection } set { section.sectionInjection = newValue } } + + /// 配置 section 视图,代理到底层 section + /// Configure section view, delegated to underlying section func config(sectionView: UICollectionView) { section.config(sectionView: sectionView) } + + /// 获取对象标识符 + /// Get object identifier var objectIdentifier: ObjectIdentifier { .init(section) } } public extension SKCAnySectionProtocol where Self: SKCSectionProtocol { + /// 当自身已经是 SKCSectionProtocol 时,返回自身 + /// When self is already SKCSectionProtocol, return self var section: SKCSectionProtocol { self } } diff --git a/Sources/SectionKit/Common/SKPrint.swift b/Sources/SectionKit/Common/SKPrint.swift index c395d50..960bfbe 100644 --- a/Sources/SectionKit/Common/SKPrint.swift +++ b/Sources/SectionKit/Common/SKPrint.swift @@ -7,15 +7,28 @@ import Foundation +/// SK 打印工具,提供条件性的调试输出功能 +/// SK print utility providing conditional debug logging functionality public struct SKPrint { + /// 打印类型枚举 + /// Print type enumeration public enum Kind: Int { + /// 高性能相关日志 + /// High performance related logs case highPerformance } + /// 启用的打印类型集合 + /// Set of enabled print types public static var kinds = Set([]) + + /// 日志标识 + /// Log identifier static let logo = "[SectionKit]" + /// 打印高性能相关信息 + /// Print high performance related information public static func highPerformance(_ items: Any...) { #if DEBUG guard kinds.contains(.highPerformance) else { return } @@ -23,6 +36,8 @@ public struct SKPrint { #endif } + /// 打印函数调用信息 + /// Print function call information public static func function(_ items: Any, _ function: StaticString = #function) { #if DEBUG debugPrint("\(logo) -> [\(function)]", items) diff --git a/Sources/SectionKit/HighPerformance/SKHighPerformanceStore.swift b/Sources/SectionKit/HighPerformance/SKHighPerformanceStore.swift index 098b666..5078fe5 100644 --- a/Sources/SectionKit/HighPerformance/SKHighPerformanceStore.swift +++ b/Sources/SectionKit/HighPerformance/SKHighPerformanceStore.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// SKHighPerformanceStore.swift +// SectionKit // // Created by linhey on 2023/4/25. // @@ -10,13 +10,24 @@ import ObjectiveC import Foundation import CoreFoundation +/// SK 高性能存储类,用于缓存尺寸计算结果以提升性能 +/// SK high performance store class for caching size calculation results to improve performance public class SKHighPerformanceStore { + /// 缓存键结构体,包含标识符和尺寸信息 + /// Cache key structure containing identifier and size information public struct CacheKey: Hashable { + /// 标识符 + /// Identifier public let id: ID + + /// 尺寸信息 + /// Size information public let size: CGSize + /// 哈希方法,用于在哈希表中存储 + /// Hash method for storing in hash table public func hash(into hasher: inout Hasher) { hasher.combine(id) hasher.combine(size.width) @@ -25,8 +36,12 @@ public class SKHighPerformanceStore { } + /// 尺寸缓存实例 + /// Size cache instance public var sizeCached: SKKVCache + /// 初始化高性能存储 + /// Initialize high performance store public init(sizeCached: SKKVCache = .init()) { self.sizeCached = sizeCached } @@ -35,15 +50,21 @@ public class SKHighPerformanceStore { public extension SKHighPerformanceStore { + /// 根据 ID 和限制尺寸进行缓存计算 + /// Cache calculation based on ID and limit size @discardableResult func cache(by id: ID, limit: CGSize, calculate: (_ limit: CGSize) -> CGSize) -> CGSize { let key = CacheKey(id: id, size: limit) + // 检查缓存中是否存在 + // Check if exists in cache if let value = sizeCached[key] { SKPrint.highPerformance("hit cache: id:\(key.id) size:\(value) limit:\(key.size)") return value } + // 执行计算并缓存结果 + // Perform calculation and cache result let calculate = calculate(limit) sizeCached[key] = calculate SKPrint.highPerformance("cache: id:\(key.id) size:\(calculate) limit:\(key.size)")