Swiftpack.co - Package - DenTelezhkin/DTModelStorage

CI codecov.io CocoaPods compatible Platform Swift Package Manager compatible Packagist


Because this project main goal is to provide storage classes and mapping/event functionality for DTCollectionViewManager and DTTableViewManager, you should probably first read, why those two frameworks exist in the first place. This is described, for example, in Why document of DTCollectionViewManager.


  • Xcode 12+
  • Swift 5.3+
  • iOS 11+ / tvOS 11+ / macCatalyst 13+


Swift Package Manager

  • Add package into Project settings -> Swift Packages


pod 'DTModelStorage'

Storage classes

The goal of storage classes is to provide datasource models for UITableView/UICollectionView. Let's take UITableView, for example. It's datasource methods mostly relates on following:

  • sections
  • items in sections
  • section headers and footers / supplementary views

Storage protocol builds upon those elements to define common interface for all storage classes. SupplementaryStorage protocol extends Storage to provide methods on supplementary models / headers/ footers.

Here are five Storage implementations provided by DTModelStorage and links to detailed documentation on them:

Please note, that all five storages support the same interface for handling supplementary models - supplementary providers. You can read more about them in dedicated document.

ViewModelMapping and EventReaction

ViewModelMapping and EventReaction classes are a part of mapping system between data models and reusable views. You can read about how they are used and why in DTCollectionViewManager Mapping document as well as DTCollectionViewManager Events document


Stars: 78


Used By

Total: 0


9.0.1 -


  • Realm subspec has been reenabled.

9.0.0 -


Realm CocoaPods subspec has been disabled due to https://github.com/realm/realm-cocoa/issues/6800

9.0.0-beta.1 -


  • ViewModelMapping.modelCondition method, that allows to create custom mapping condition, but infers model type from mapping. Behavior of this method is identical to ModelTransfer.modelCondition method, except that new method does not require cell or view to implement ModelTransfer protocol.
  • MemoryStorage.insertItems(_:at:) method, that allows inserting collection starting from provided indexPath. This is useful, for example, if you are using pagination, and want to insert new page of items between old pages and loading indicator.


This release requires Swift 5.3.

Some context: this release heavily relies on where clauses on contextually generic declarations, that are only available in Swift 5.3 - SE-0267.

  • DTModelStorage/Realm subspec requires RealmSwift 5.2 and higher for minimum iOS 9 deployment target.


  • ViewModelMapping has been reworked to generic class to capture both View and Model type.
  • ViewModelMappingProtocol protocol has been introduced to represent type-erased interface for ViewModelMapping so that ViewModelMappingProtocol instances can be stored in array, and be called without generic information.
  • EventReaction class has been reworked to not contain ViewModelMapping instance. ViewModelMapping class will now instead have an array of EventReaction instances attached to it. This way it's now possible to restrict events to only happen if current ViewModelMapping is compatible for requested model/view/location/mapping condition.
  • ViewModelMapping convenience methods eventsModelMapping and eventsViewMapping have been removed.
  • mappingCandidates method now returns ViewModelMappingProtocol instead of ViewModelMapping
  • performReaction methods now accept IndexPath for location parameter instead of Any.
  • Event reactions are moved from extension on [ViewModelMapping] to static methods on EventReaction due to Swift inability to call methods on sequences that contain protocols.
  • mappingCandidates method has been moved to ViewType type.
  • EventReaction has new initializers with more specific names.
  • insertItems(_:to:) method is no longer throwing. Anomaly is still produced, if count of models differs from count of indexPaths.


  • MemoryStorage.defersDatasourceUpdates property. Deferring datasource updates and executing them inside of performBatchUpdates block turned out to be the only stable and correct way to apply updates to both UI and datasource. It's highly recommended to leave this property on. It is now deprecated, and may be removed in the future release, maintaining current default behaviour.
  • SectionModel.setItems(_:) method. Set items directly through items property.

8.1.0 -


  • Deployment targets - iOS 11 / tvOS 11.
  • Minimum Swift version required: 5.0
  • Realm dependency updated to Realm 5.

Please note, that this framework version source is identical to previous version (apart from some small Realm adjustments), which supports iOS 8 / tvOS 9 / Swift 4.0 and higher.

8.0.0 -

8.0.0-beta.2 -

  • Added support for Xcode versions, that are older than Xcode 11.

8.0.0-beta.1 -

This is a major release with some breaking changes, please read DTModelStorage 8.0 Migration Guide


  • bundle property on ViewModelMapping, that exposes recommended bundle to be used when searching for resources of given mapping.
  • Setter for SingleSectionStorage.items property.
  • Section.item(at:) method.
  • ProxyDiffableDataSourceStorage that serves as a bridge between DTTableViewManager/DTCollectionViewManager and diffable datasource classes(UITableViewDiffableDataSource`UICollectionViewDiffableDataSource`).


  • configureForTableViewUsage, configureForCollectionViewUsage, headerModel(forSection:), footerModel(forSection:), have been moved to protocol extensions instead of being implemented in BaseStorage class. As a consequence, BaseStorage no longer confirms to HeaderFooterStorage protocol.


Identifiable protocol has been renamed to EntityIdentifiable protocol to avoid unwanted clashes with Foundation.Identifiable protocol, that is available on iOS 13 and higher.

Complete rewrite of header/footer/supplementary model handling. Instead of several implementations and model storages, the API now consists of three closure based properties on SupplementaryStorage protocol : headerModelProvider, footerModelProvider and supplementaryModelProvider. All storage classes implement this protocol (MemoryStorage, CoreDataStorage, RealmStorage, SingleSectionStorage, ProxyDiffableDataSourceStorage).

Storage protocols and classes have been restructured:

  • SupplementaryAccessible renamed to SectionLocatable
  • HeaderFooterStorage and HeaderFooterSettable have been removed
  • HeaderFooterStorage functionality mostly has been merged into new protocol SupplementaryStorage
  • BaseStorage has been split into BaseSupplementaryStorage and BaseUpdateDeliveringStorage that inherits from it.

Several methods continue to work, but are now bridging to new closure-based API:

  • setSectionHeaderModels
  • setSectionFooterModels
  • headerModel(forSection:)
  • footerModel(forSection:)
  • supplementaryModel(ofKind:forSectionAt:)

setSectionHeaderModels and setSectionFooterModels, as well as new closure-based API do not call reloadData method, as they were doing before. If you need to reset section headers/footers/supplementaries, consider calling StorageUpdating.storageNeedsReloading() method manually.

All methods that allowed to set header/footer/supplementary models partially, for a specific section or specific supplementary kind, have been made unavailable or removed.

CoreDataStorage now sets headerModelProvider closure to allow using FetchedResultsController section name as header instead of having arbitrary logic that compared supplementaryKind to displaySectionNameForSupplementaryKinds property, which is also made unavailable.


  • Deprecated MemoryStorageError.BatchInsertionReason enum.
  • Deprecated ViewModelMappingCustomizing protocol.
  • sections method on Storage protocol. It is replaced by more perfomant numberOfSections() and numberOfItems(inSection:) methods.
  • sections method on CoreDataStorage and SingleSectionStorage
  • items property on Section protocol. It is replaced by item(at:) method.

7.4.1 -


  • bundle property on ViewModelMapping, that exposes recommended bundle to be used when searching for resources of given mapping.


  • setItemsForAllSections method now properly removes all sections prior to setting new ones. This prevents a bug, where old sections could stay, if this method was called with fewer number of sections.

7.4.0 -


  • Support for Swift Package Manager in Xcode 11


  • Slightly improved RealmStorage item(at:) method perfomance.
  • Improved StorageUpdate description.
  • ViewModelMapping.xibName can now be changed inside of mapping blocks to allow changing xibName per mapping.

7.3.0 -


  • Support for Swift 5 and Xcode 10.2


  • ViewModelMappingCustomizing protocol. Please switch to using mapping conditions instead.


  • Support for Xcode 9 and Swift 3

7.2.1 -

  • Make enqueueDatasourceUpdate method and enqueuedDatasourceUpdates property public to allow building custom storages that defer datasource updates.

7.2.0 -


  • Single section storage classes with support for automatic diffing.

    SingleSectionStorage classes are now a recommended way of handling items in single section in more powerful way than MemoryStorage class.

    Read more about it in README.

  • Support for Swift 4.2 and Xcode 10.

  • Convenience methods for conditional mappings and anomalies

    • Method to create MappingCondition from ModelTransfer objects
    • Ability to silence anomalies using enum or closure

7.1.0 -



  • Support for Xcode 10 (beta 1) with Swift 4.1 and Swift 4.2.


  • Crash that could happen if move operation for MemoryStorage happened from and to the same section with not enough items in section.

7.0.3 -

  • Updates for Xcode 9.3 and Swift 4.1

7.0.2 -

  • Properly collect all updates from updateWithoutAnimations block.

7.0.1 -

  • Fixed a bug, that prevented datasource from being updated when updateWithoutAnimations method on MemoryStorage was used.

7.0.0 -

7.0.0-beta.1 -

  • Implemented mechanism for deferring datasource updates of MemoryStorage. When turned on, updates are no longer applied automatically, but can be applied calling StorageUpdate.applyDeferredDatasourceUpdates() method. Keep in mind, that not only datasource updates are not applied, but object and section changes are also empty until updates are applied. This behaviour is turned on by default, to disable it, call
MemoryStorage.defersDatasourceUpdates = false
  • Ream podspec now requires Realm version 3.x

6.0.0 -

  • Fixed warnings for Xcode 9.1 / Swift 4.0.2

6.0.0-beta.2 -

  • Build with Xcode 9.0 release.

6.0.0-beta.1 -

This is major release, containing breaking API changes, please read DTTableViewManager 6.0 Migration Guide

  • MemoryStorage now has a convenience method for moving item without animations: moveItemWithoutAnimation(from:to:).
  • EventReaction class now has 4 and 5 argument reactions
  • All storage protocols are now class-bound.
  • Implemented mapping conditions. ViewModelMapping was changed to be able to work with mapping blocks.


  • RealmStorage is not included in Carthage releases.
  • setItems method, that accepted array of arrays of items to set items for all sections, has been renamed to setItemsForAllSections to provide more clarity and not to clash with setItems(_:forSection:) method.

5.1.0 -

  • Swift 3.2 support(Xcode 9 beta 1).
  • RealmStorage now accepts RealmCollection objects into section, thus allowing List and LinkingObjects to be used(previously only Results objects could be used in section).

5.0.1 -

  • Improved handling of NSFetchedResultsControllerDelegate NSFetchedResultsChangeType.update change type in cases, where object inserts/removal/moves is used simultaneously with object updates(#17).

5.0.0 -

  • Reworked EventReaction class to use ViewModelMapping to properly identify not only model and ViewType, but also viewClass. This allows event reactions to run for cases where two view subclasses, conforming to ModelTransfer, use the same model, and have similar events.

4.1.0 -

  • Adds setItems(_:) method, that allows to set items for all sections in MemoryStorage.

4.0.0 -

  • StorageUpdate properties, that tracked changes independently of each other, have been replaced with objectChanges, sectionChanges arrays, that track all changes in order they occured
  • StorageUpdate now has updatedObjects dictionary, that allow tracking objects, that have been updated, along with corresponding indexPath. It is done because UITableView and UICollectionView defer cell updates after insertions and deletions are completed, and therefore shift indexPaths. For example, if you were to insert 0 item and update it, UITableView would think that you are updating 1 item instead of 0, because it happens in single animation block and 0 item becomes 1.

3.0.0 -

No changes from previous betas.

3.0.0-beta.3 -

  • Requires Realm 2.0 and higher.
  • Fixes crash, that happens, when subscribing to Realm notifications and Realm is read-only(thanks, @augmentedworks!)

3.0.0-beta.2 -

  • Enables RealmStorage with RealmSwift dependency

3.0.0-beta.1 -

Swift 3.0 and higher is required for this version of framework.

Note. Beta 1 Does not include RealmStorage subspec due to RealmSwift.framework podspec issues


  • UIReaction class has been replaced with new EventReaction class, that allows more flexible and powerful events usage
  • Supplementary models are now stored in [String:[Int:Any]] instead of [String:Any] to support supplementary models, whose position is determined by indexPath in UICollectionView. SupplementaryStorageProtocol, SupplementaryAccessible protocols have been reworked to reflect those changes.
  • MemoryStorageErrors have been made an Error type following conventions from SE-0112.


  • MemoryStorage and RealmStorage now implement SectionLocationIdentifyable protocol, allowing any section to find out, what it's index is.
  • SectionModel and RealmSection gained currentSectionIndex property, that shows index of section in sections array.
  • displaySectionNameForSupplementaryKinds property on CoreDataStorage, that defines, for which supplementary kinds NSFetchedResultsController sectionName should be used as a data model.
  • removeItemsFromSection method on MemoryStorage, that allows to remove all items from specific section


  • itemForCellClass:atIndexPath:, itemForHeaderClass:atSectionIndex:, itemsForFooterClass:atSectionIndex:
  • makeNSIndexSet method, because Swift 3 allows to directly create IndexSet from both Array and Set.