How to Perform Batch Updates (Insert, Delete, Reload) with SKCManager in SectionKit

SKCManager provides thread-safe, animated batch update APIs that translate high-level section operations into corresponding UICollectionView method calls, eliminating manual index path calculations.

The linhay/sectionkit repository implements a section-driven architecture for UICollectionView that abstracts complex data source management into discrete section objects. When you perform batch updates with SKCManager, the class coordinates between your section models and the underlying collection view through a combination of section-level methods and cell-level injection protocols.

Core Architecture Components

Understanding the internal structure of SectionKit clarifies how batch updates propagate through the system. The framework relies on four primary components to manage state changes:

SKCManager (defined in Sources/SectionKit/CollectionBase/SKCManager.swift, lines 62-89) serves as the central coordinator. It maintains the publishers.sectionsSubject that holds the current array of sections and exposes the public insert(), delete(), and reload() APIs.

SKCSectionInjection (defined in Sources/SectionKit/CollectionBase/SKCSectionInjection.swift, lines 20-70) provides per-section batch helpers. Each section instance receives an injection object that maps cell-level changes to the view provider.

SKCSectionViewProvider (implemented within SKCSectionInjection.swift, lines 76-108) translates abstract ActionKind enums into concrete UICollectionView operations like insertItems, deleteSections, or reloadData.

SKCBaseSectionProtocol (aliased in Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift, lines 11-13) defines the contract that all section objects must fulfill to participate in the batch update system.

Performing Section-Level Batch Updates

SKCManager exposes three primary methods for modifying the section hierarchy. These methods handle index calculation, injection binding, and the appropriate UICollectionView animation automatically.

Inserting Sections

The insert(_:at:) method adds new sections at a specified index. According to the implementation in SKCManager.swift (lines 9-21), this method first binds the new sections to injection objects, validates the section array through security(check:), then determines whether to use insertSections or fall back to reloadData based on the global configuration.

func insert(_ input: [SKCBaseSectionProtocol], at: Int) {
    guard !input.isEmpty else { return }
    var sections = sections
    sections.insert(contentsOf: bind(sections: input, start: at), at: at)
    security(check: sections)
    if let sectionView = sectionView,
       !configuration.replaceInsertWithReloadData {
        publishers.sectionsSubject.send(sections)
        sectionView.insertSections(IndexSet(integersIn: at..<(at + input.count)))
    } else {
        reload(sections)
    }
}

To insert a single section at index 1:

let newSection = MySection(models: freshData)
manager.insert([newSection], at: 1)

Deleting Sections

The delete(_:) method removes existing sections from the collection view. It updates the internal sections array and invokes deleteSections on the collection view unless replaceDeleteWithReloadData is enabled in the configuration.

let sectionsToRemove: [SKCBaseSectionProtocol] = [headerSection, footerSection]
manager.delete(sectionsToRemove)

Reloading Sections

The reload(_:) method refreshes existing sections without removing them from the hierarchy. This triggers reloadSections on the collection view and updates the section injection bindings.

manager.reload([profileSection])

Executing Cell-Level Batch Updates

When you need to modify individual rows within a specific section rather than the entire section, use the SKCSectionInjection API. Each section conforming to SKCBaseSectionProtocol receives an optional sectionInjection property that provides cell-specific batch methods.

These methods are implemented in SKCSectionInjection.swift (lines 20-70) and forward actions to the underlying SKCSectionViewProvider:

section.sectionInjection?.insert(cell: [0, 2])   // Insert at indices 0 and 2
section.sectionInjection?.delete(cell: [3])    // Remove cell at index 3
section.sectionInjection?.reload(cell: [1, 5]) // Reload cells at indices 1 and 5

The injection object translates these calls into UICollectionView batch updates through an internal events dictionary that maps ActionKind to closure handlers (lines 76-108 in SKCSectionInjection.swift). This ensures that cell-level changes respect the current animation context and maintain index consistency.

Grouping Multiple Operations with pick()

Complex UI transitions often require simultaneous section and cell modifications. The pick() method in SKCManager (lines 71-73) wraps multiple operations into a single performBatchUpdates block, ensuring atomic animations and preventing visual flicker.

manager.pick {
    // Section-level changes
    manager.insert([newSection], at: 2)
    manager.delete([oldSection])
    manager.reload([updatedSection])
    
    // Cell-level changes within the updated section
    updatedSection.sectionInjection?.delete(cell: [5])
    updatedSection.sectionInjection?.insert(cell: [2, 3])
}

The implementation simply forwards to the collection view's native batch update mechanism:

func pick(_ updates: () -> Void, completion: ((_ flag: Bool) -> Void)? = nil) {
    sectionView?.performBatchUpdates(updates, completion: completion)
}

This approach guarantees that all index calculations remain valid throughout the animation block, as UICollectionView snapshots the state before executing the updates.

Configuration Options for Batch Behavior

SKCManager exposes global configuration flags that control fallback behavior when animation conflicts arise. These settings reside in the configuration property and affect how the manager translates high-level calls:

  • replaceInsertWithReloadData: When true, redirects insert() calls to reloadData() instead of insertSections.
  • replaceDeleteWithReloadData: When true, redirects delete() calls to reloadData() instead of deleteSections.

Enable these flags during development to diagnose animation crashes caused by inconsistent data states:

SKCManager.configuration.replaceInsertWithReloadData = true
SKCManager.configuration.replaceDeleteWithReloadData = true

Summary

  • SKCManager centralizes batch updates through insert(), delete(), and reload() methods defined in SKCManager.swift (lines 62-89).
  • Section updates automatically handle index calculation and injection binding before calling the corresponding UICollectionView methods.
  • SKCSectionInjection provides cell-level batch operations via insert(cell:), delete(cell:), and reload(cell:) as implemented in SKCSectionInjection.swift (lines 20-70).
  • The pick() method groups multiple section and cell operations into a single performBatchUpdates block for atomic animations.
  • Global configuration flags allow fallback to reloadData() when debugging complex transition states.

Frequently Asked Questions

How does SKCManager handle index consistency during batch updates?

SKCManager maintains index consistency by updating the internal sections array before invoking any UICollectionView methods. When using pick(), the framework relies on UICollectionView.performBatchUpdates to snapshot the state prior to execution. The security(check:) method validates injection mappings in DEBUG builds to ensure every section has a valid provider before animation begins.

Can I mix section-level and cell-level updates in the same batch animation?

Yes. Call manager.pick() and include both manager-level methods (insert, delete, reload) and injection-level methods (sectionInjection?.insert(cell:) etc.) within the closure. The SKCSectionViewProvider routes each action to the appropriate UICollectionView method while the batch update block ensures all changes animate simultaneously.

What happens if a section lacks a valid injection during batch updates?

In DEBUG builds, SKCManager invokes security(check:) after modifying the sections array, which validates that every section has a non-nil sectionInjection. If a section lacks injection, the check triggers an assertion failure pointing to the unconfigured section. In RELEASE builds, the check is skipped for performance, but missing injections may result in silent update failures.

When should I use reloadData instead of batch updates?

Use reloadData when your data state becomes inconsistent or when the cost of calculating index differences exceeds the benefit of animation. Set SKCManager.configuration.replaceInsertWithReloadData or replaceDeleteWithReloadData to true to force this behavior globally, or call manager.reload(sections) directly to bypass individual insert/delete animations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →