Skip to content

Commit

Permalink
Uses native implementation when available
Browse files Browse the repository at this point in the history
  • Loading branch information
nobre84 committed Apr 11, 2023
1 parent a457cf6 commit 77c8122
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6BB762CB22B455170050DC03"
BuildableName = "DiffableDataSources.framework"
BlueprintName = "DiffableDataSources"
ReferencedContainer = "container:DiffableDataSources.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
Expand All @@ -39,17 +48,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6BB762CB22B455170050DC03"
BuildableName = "DiffableDataSources.framework"
BlueprintName = "DiffableDataSources"
ReferencedContainer = "container:DiffableDataSources.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -70,8 +68,6 @@
ReferencedContainer = "container:DiffableDataSources.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
105 changes: 104 additions & 1 deletion Sources/DiffableDataSourceSnapshot.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,71 @@
import UIKit

/// A class for backporting `NSDiffableDataSourceSnapshot` introduced in iOS 13.0+, macOS 10.15+, tvOS 13.0+.
/// Represents the mutable state of diffable data source of UI.
public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable> {
internal var structure = SnapshotStructure<SectionIdentifierType, ItemIdentifierType>()

private let forceFallback: Bool
private var _nativeSnapshot: Any?
@available(iOS 13.0, *)
internal var nativeSnapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> {
get {
return _nativeSnapshot as! NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>
}
set {
_nativeSnapshot = newValue
}
}

/// Creates a new empty snapshot object.
public init() {}
public init() {
self.init(forceFallback: false)
}

internal init(forceFallback: Bool) {
self.forceFallback = forceFallback
if #available(iOS 13.0, *), !forceFallback {
nativeSnapshot = .init()
return
}
}

@available(iOS 13.0, *)
static func from(nativeSnapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>) -> Self {
var snapshot = DiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>()
snapshot.nativeSnapshot = nativeSnapshot
return snapshot
}

/// The number of item identifiers in the snapshot.
public var numberOfItems: Int {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.numberOfItems
}
return itemIdentifiers.count
}

/// The number of section identifiers in the snapshot.
public var numberOfSections: Int {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.numberOfSections
}
return sectionIdentifiers.count
}

/// All section identifiers in the snapshot.
public var sectionIdentifiers: [SectionIdentifierType] {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.sectionIdentifiers
}
return structure.allSectionIDs
}

/// All item identifiers in the snapshot.
public var itemIdentifiers: [ItemIdentifierType] {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.itemIdentifiers
}
return structure.allItemIDs
}

Expand All @@ -33,6 +76,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
///
/// - Returns: The number of item identifiers in the specified section.
public func numberOfItems(inSection identifier: SectionIdentifierType) -> Int {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.numberOfItems(inSection: identifier)
}
return itemIdentifiers(inSection: identifier).count
}

Expand All @@ -43,6 +89,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
///
/// - Returns: The item identifiers in the specified section.
public func itemIdentifiers(inSection identifier: SectionIdentifierType) -> [ItemIdentifierType] {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.itemIdentifiers(inSection: identifier)
}
return structure.items(in: identifier)
}

Expand All @@ -53,6 +102,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
///
/// - Returns: A section identifier containing the specified item.
public func sectionIdentifier(containingItem identifier: ItemIdentifierType) -> SectionIdentifierType? {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.sectionIdentifier(containingItem: identifier)
}
return structure.section(containing: identifier)
}

Expand All @@ -63,6 +115,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
///
/// - Returns: An index of the specified item.
public func indexOfItem(_ identifier: ItemIdentifierType) -> Int? {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.indexOfItem(identifier)
}
return itemIdentifiers.firstIndex { $0.isEqualHash(to: identifier) }
}

Expand All @@ -73,6 +128,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
///
/// - Returns: An index of the specified section.
public func indexOfSection(_ identifier: SectionIdentifierType) -> Int? {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.indexOfSection(identifier)
}
return sectionIdentifiers.firstIndex { $0.isEqualHash(to: identifier) }
}

Expand All @@ -82,6 +140,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifiers: The item identifiers to be appended.
/// - sectionIdentifier: An identifier of section to append the given identiciers.
public mutating func appendItems(_ identifiers: [ItemIdentifierType], toSection sectionIdentifier: SectionIdentifierType? = nil) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.appendItems(identifiers, toSection: sectionIdentifier)
}
structure.append(itemIDs: identifiers, to: sectionIdentifier)
}

Expand All @@ -91,6 +152,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifiers: The item identifiers to be inserted.
/// - beforeIdentifier: An identifier of item.
public mutating func insertItems(_ identifiers: [ItemIdentifierType], beforeItem beforeIdentifier: ItemIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.insertItems(identifiers, beforeItem: beforeIdentifier)
}
structure.insert(itemIDs: identifiers, before: beforeIdentifier)
}

Expand All @@ -100,6 +164,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifiers: The item identifiers to be inserted.
/// - afterIdentifier: An identifier of item.
public mutating func insertItems(_ identifiers: [ItemIdentifierType], afterItem afterIdentifier: ItemIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.insertItems(identifiers, afterItem: afterIdentifier)
}
structure.insert(itemIDs: identifiers, after: afterIdentifier)
}

Expand All @@ -108,11 +175,17 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - Parameters:
/// - identifiers: The item identifiers to be deleted.
public mutating func deleteItems(_ identifiers: [ItemIdentifierType]) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.deleteItems(identifiers)
}
structure.remove(itemIDs: identifiers)
}

/// Deletes the all items in the snapshot.
public mutating func deleteAllItems() {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.deleteAllItems()
}
structure.removeAllItems()
}

Expand All @@ -122,6 +195,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifier: An item identifier to be moved.
/// - toIdentifier: An identifier of item.
public mutating func moveItem(_ identifier: ItemIdentifierType, beforeItem toIdentifier: ItemIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.moveItem(identifier, beforeItem: toIdentifier)
}
structure.move(itemID: identifier, before: toIdentifier)
}

Expand All @@ -131,6 +207,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifier: An item identifier to be moved.
/// - toIdentifier: An identifier of item.
public mutating func moveItem(_ identifier: ItemIdentifierType, afterItem toIdentifier: ItemIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.moveItem(identifier, afterItem: toIdentifier)
}
structure.move(itemID: identifier, after: toIdentifier)
}

Expand All @@ -139,6 +218,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - Parameters:
/// - identifiers: The item identifiers to be reloaded.
public mutating func reloadItems(_ identifiers: [ItemIdentifierType]) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.reloadItems(identifiers)
}
structure.update(itemIDs: identifiers)
}

Expand All @@ -147,6 +229,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - Parameters:
/// - identifiers: The section identifiers to be appended.
public mutating func appendSections(_ identifiers: [SectionIdentifierType]) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.appendSections(identifiers)
}
structure.append(sectionIDs: identifiers)
}

Expand All @@ -156,6 +241,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifiers: The section identifiers to be inserted.
/// - toIdentifier: An identifier of setion.
public mutating func insertSections(_ identifiers: [SectionIdentifierType], beforeSection toIdentifier: SectionIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.insertSections(identifiers, beforeSection: toIdentifier)
}
structure.insert(sectionIDs: identifiers, before: toIdentifier)
}

Expand All @@ -165,6 +253,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifiers: The section identifiers to be inserted.
/// - toIdentifier: An identifier of setion.
public mutating func insertSections(_ identifiers: [SectionIdentifierType], afterSection toIdentifier: SectionIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.insertSections(identifiers, afterSection: toIdentifier)
}
structure.insert(sectionIDs: identifiers, after: toIdentifier)
}

Expand All @@ -173,6 +264,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - Parameters:
/// - identifiers: The section identifiers to be deleted.
public mutating func deleteSections(_ identifiers: [SectionIdentifierType]) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.deleteSections(identifiers)
}
structure.remove(sectionIDs: identifiers)
}

Expand All @@ -182,6 +276,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifier: A section identifier to be moved.
/// - toIdentifier: An identifier of section.
public mutating func moveSection(_ identifier: SectionIdentifierType, beforeSection toIdentifier: SectionIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.moveSection(identifier, beforeSection: toIdentifier)
}
structure.move(sectionID: identifier, before: toIdentifier)
}

Expand All @@ -191,6 +288,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - identifier: A section identifier to be moved.
/// - toIdentifier: An identifier of section.
public mutating func moveSection(_ identifier: SectionIdentifierType, afterSection toIdentifier: SectionIdentifierType) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.moveSection(identifier, afterSection: toIdentifier)
}
structure.move(sectionID: identifier, after: toIdentifier)
}

Expand All @@ -199,6 +299,9 @@ public struct DiffableDataSourceSnapshot<SectionIdentifierType: Hashable, ItemId
/// - Parameters:
/// - identifiers: The section identifiers to be reloaded.
public mutating func reloadSections(_ identifiers: [SectionIdentifierType]) {
if #available(iOS 13.0, *), !forceFallback {
return nativeSnapshot.reloadSections(identifiers)
}
structure.update(sectionIDs: identifiers)
}
}
4 changes: 2 additions & 2 deletions Sources/Internal/DiffableDataSourceCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ final class DiffableDataSourceCore<SectionIdentifierType: Hashable, ItemIdentifi
}
}

func snapshot() -> DiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> {
var snapshot = DiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>()
func snapshot(forceFallback: Bool) -> DiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> {
var snapshot = DiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>(forceFallback: forceFallback)
snapshot.structure.sections = currentSnapshot.structure.sections
return snapshot
}
Expand Down
Loading

0 comments on commit 77c8122

Please sign in to comment.