diff --git a/Sources/Algorithm.swift b/Sources/Algorithm.swift index d9ee9a5..30a64bc 100644 --- a/Sources/Algorithm.swift +++ b/Sources/Algorithm.swift @@ -19,7 +19,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C /// /// - Complexity: O(n) @inlinable - public init(source: Collection, target: Collection) { + init(source: Collection, target: Collection) { self.init(source: source, target: target, section: 0) } @@ -44,7 +44,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C /// /// - Complexity: O(n) @inlinable - public init(source: Collection, target: Collection, section: Int) { + init(source: Collection, target: Collection, section: Int) { let sourceElements = ContiguousArray(source) let targetElements = ContiguousArray(target) @@ -151,7 +151,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C /// /// - Complexity: O(n) @inlinable - public init(source: Collection, target: Collection) { + init(source: Collection, target: Collection) { typealias Section = Collection.Element typealias SectionIdentifier = Collection.Element.DifferenceIdentifier typealias Element = Collection.Element.Collection.Element @@ -327,7 +327,11 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C for targetElementIndex in targetElements.indices { untrackedSourceIndex = untrackedSourceIndex.flatMap { index in - sourceElementTraces[sourceSectionIndex].suffix(from: index).index { !$0.isTracked } + #if swift(>=5.0) + return sourceElementTraces[sourceSectionIndex].suffix(from: index).firstIndex { !$0.isTracked } + #else + return sourceElementTraces[sourceSectionIndex].suffix(from: index).index { !$0.isTracked } + #endif } let targetElementPath = ElementPath(element: targetElementIndex, section: targetSectionIndex) @@ -537,7 +541,11 @@ internal func differentiate( // Record the updates/moves/insertions. for targetIndex in target.indices { untrackedSourceIndex = untrackedSourceIndex.flatMap { index in - sourceTraces.suffix(from: index).index { !$0.isTracked } + #if swift(>=5.0) + return sourceTraces.suffix(from: index).firstIndex { !$0.isTracked } + #else + return sourceTraces.suffix(from: index).index { !$0.isTracked } + #endif } if let sourceIndex = targetReferences[targetIndex] { @@ -653,14 +661,11 @@ internal final class IndicesReference { /// Dictionary key using UnsafePointer for performance optimization. @usableFromInline internal struct TableKey: Hashable { - @usableFromInline - internal let hashValue: Int @usableFromInline internal let pointer: UnsafePointer @inlinable internal init(pointer: UnsafePointer) { - self.hashValue = pointer.pointee.hashValue self.pointer = pointer } @@ -669,11 +674,15 @@ internal struct TableKey: Hashable { return lhs.hashValue == rhs.hashValue && (lhs.pointer.distance(to: rhs.pointer) == 0 || lhs.pointer.pointee == rhs.pointer.pointee) } + + public func hash(into hasher: inout Hasher) { + hasher.combine(pointer.pointee) + } } internal extension MutableCollection where Element: MutableCollection, Index == Int, Element.Index == Int { @inlinable - internal subscript(path: ElementPath) -> Element.Element { + subscript(path: ElementPath) -> Element.Element { get { return self[path.section][path.element] } set { self[path.section][path.element] = newValue } } diff --git a/Sources/Changeset.swift b/Sources/Changeset.swift index 327429b..16e6561 100644 --- a/Sources/Changeset.swift +++ b/Sources/Changeset.swift @@ -65,7 +65,7 @@ public struct Changeset { public extension Changeset { /// The number of section changes. @inlinable - public var sectionChangeCount: Int { + var sectionChangeCount: Int { return sectionDeleted.count + sectionInserted.count + sectionUpdated.count @@ -74,7 +74,7 @@ public extension Changeset { /// The number of element changes. @inlinable - public var elementChangeCount: Int { + var elementChangeCount: Int { return elementDeleted.count + elementInserted.count + elementUpdated.count @@ -83,25 +83,25 @@ public extension Changeset { /// The number of all changes. @inlinable - public var changeCount: Int { + var changeCount: Int { return sectionChangeCount + elementChangeCount } /// A Boolean value indicating whether has section changes. @inlinable - public var hasSectionChanges: Bool { + var hasSectionChanges: Bool { return sectionChangeCount > 0 } /// A Boolean value indicating whether has element changes. @inlinable - public var hasElementChanges: Bool { + var hasElementChanges: Bool { return elementChangeCount > 0 } /// A Boolean value indicating whether has changes. @inlinable - public var hasChanges: Bool { + var hasChanges: Bool { return changeCount > 0 } } diff --git a/Sources/Extensions/AppKitExtension.swift b/Sources/Extensions/AppKitExtension.swift index 520e076..a5a0efb 100644 --- a/Sources/Extensions/AppKitExtension.swift +++ b/Sources/Extensions/AppKitExtension.swift @@ -15,12 +15,23 @@ public extension NSTableView { /// updates should be stopped and performed reloadData. Default is nil. /// - setData: A closure that takes the collection as a parameter. /// The collection should be set to data-source of NSTableView. + func reload( using stagedChangeset: StagedChangeset, with animation: @autoclosure () -> NSTableView.AnimationOptions, interrupt: ((Changeset) -> Bool)? = nil, setData: (C) -> Void ) { + #if swift(>=5.0) + reload( + using: stagedChangeset, + deleteRowsAnimation: animation(), + insertRowsAnimation: animation(), + reloadRowsAnimation: animation(), + interrupt: interrupt, + setData: setData + ) + #else reload( using: stagedChangeset, deleteRowsAnimation: animation, @@ -29,6 +40,7 @@ public extension NSTableView { interrupt: interrupt, setData: setData ) + #endif } /// Applies multiple animated updates in stages using `StagedChangeset`. diff --git a/Sources/Extensions/UIKitExtension.swift b/Sources/Extensions/UIKitExtension.swift index e40f75d..a63c5e9 100644 --- a/Sources/Extensions/UIKitExtension.swift +++ b/Sources/Extensions/UIKitExtension.swift @@ -21,6 +21,19 @@ public extension UITableView { interrupt: ((Changeset) -> Bool)? = nil, setData: (C) -> Void ) { + #if swift(>=5.0) + reload( + using: stagedChangeset, + deleteSectionsAnimation: animation(), + insertSectionsAnimation: animation(), + reloadSectionsAnimation: animation(), + deleteRowsAnimation: animation(), + insertRowsAnimation: animation(), + reloadRowsAnimation: animation(), + interrupt: interrupt, + setData: setData + ) + #else reload( using: stagedChangeset, deleteSectionsAnimation: animation, @@ -32,6 +45,7 @@ public extension UITableView { interrupt: interrupt, setData: setData ) + #endif } /// Applies multiple animated updates in stages using `StagedChangeset`. diff --git a/Sources/StagedChangeset.swift b/Sources/StagedChangeset.swift index a917203..bd22912 100644 --- a/Sources/StagedChangeset.swift +++ b/Sources/StagedChangeset.swift @@ -43,7 +43,7 @@ public struct StagedChangeset { } } -extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection, MutableCollection { +extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection { @inlinable public init() { self.init([]) @@ -76,6 +76,10 @@ extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection, M } } +#if !compiler(>=5.0) && compiler(>=4.0) +extension StagedChangeset: MutableCollection {} +#endif + extension StagedChangeset: Equatable where Collection: Equatable { @inlinable public static func == (lhs: StagedChangeset, rhs: StagedChangeset) -> Bool {