diff --git a/Package.resolved b/Package.resolved index fde41db..975135d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,21 +1,12 @@ { "pins" : [ - { - "identity" : "swiftui-gesture-velocity", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/swiftui-gesture-velocity", - "state" : { - "revision" : "9c83f8995f9e5efc29db2fca4b9ff058283f1603", - "version" : "1.0.0" - } - }, { "identity" : "swiftui-support", "kind" : "remoteSourceControl", "location" : "https://github.com/FluidGroup/swiftui-support", "state" : { - "revision" : "8ef53190c33bd345e7a95ef504dafe0f85ad9c4d", - "version" : "0.4.1" + "revision" : "c610c1e46c14c4660beb4ef7fe0241941dbecdc6", + "version" : "0.5.0" } } ], diff --git a/Sources/DynamicList/DynamicListView.swift b/Sources/DynamicList/DynamicListView.swift index 37406a5..12a3555 100644 --- a/Sources/DynamicList/DynamicListView.swift +++ b/Sources/DynamicList/DynamicListView.swift @@ -608,3 +608,4 @@ extension EnvironmentValues { set { self[CellContextKey.self] = newValue } } } + diff --git a/Sources/DynamicList/NSDiffableDataSourceSnapshot+Unique.swift b/Sources/DynamicList/NSDiffableDataSourceSnapshot+Unique.swift new file mode 100644 index 0000000..3c2053c --- /dev/null +++ b/Sources/DynamicList/NSDiffableDataSourceSnapshot+Unique.swift @@ -0,0 +1,61 @@ + +import UIKit + +public enum DiffableDataSourceError: Error { + case duplicatedSectionIdentifiers(Set) + case duplicatedItemIdentifiers(Set) +} + +extension NSDiffableDataSourceSnapshot { + + public mutating func safeAppendSections( + _ sections: [SectionIdentifierType] + ) throws { + + var sectionSet: Set = [] + + for section in sections { + let (inserted, _) = sectionSet.insert(section) + guard inserted else { + throw DiffableDataSourceError.duplicatedSectionIdentifiers([section]) + } + } + + + var set = Set(sectionIdentifiers) + set.formIntersection(sections) + + if set.isEmpty { + appendSections(sections) + } else { + throw DiffableDataSourceError.duplicatedSectionIdentifiers(set) + } + + } + + public mutating func safeAppendItems( + _ items: [ItemIdentifierType], + intoSection sectionIdentifier: SectionIdentifierType? = nil + ) throws { + + var itemSet: Set = [] + + for item in items { + let (inserted, _) = itemSet.insert(item) + guard inserted else { + throw DiffableDataSourceError.duplicatedItemIdentifiers([item]) + } + } + + var set = Set(itemIdentifiers) + set.formIntersection(items) + + if set.isEmpty { + appendItems(items, toSection: sectionIdentifier) + } else { + throw DiffableDataSourceError.duplicatedItemIdentifiers(set) + } + + } + +} diff --git a/Tests/DynamicListTests/swift_dynamic_listTests.swift b/Tests/DynamicListTests/swift_dynamic_listTests.swift index 0187cc8..e4ffaef 100644 --- a/Tests/DynamicListTests/swift_dynamic_listTests.swift +++ b/Tests/DynamicListTests/swift_dynamic_listTests.swift @@ -1,12 +1,38 @@ import XCTest + @testable import DynamicList final class swift_dynamic_listTests: XCTestCase { - func testExample() throws { - // XCTest Documenation - // https://developer.apple.com/documentation/xctest + func testDiffable_append_duplicated() throws { + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections(["A"]) + + do { + try snapshot.safeAppendItems([0, 0]) + XCTFail() + } catch { - // Defining Test Cases and Test Methods - // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods } + } + + func testDiffable_append_duplicated_2() throws { + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections(["A"]) + snapshot.appendItems([0]) + + do { + try snapshot.safeAppendItems([0]) + XCTFail() + } catch { + + } + } + + func testIntersect() throws { + + XCTAssertEqual(Set([1,2]).intersection([3,4]).isEmpty, true) + + } }