MemoryStorage
encapsulates storage of data models in memory. It's basically an Array of SectionModel
items, which contain array of items for current section.
let storage = MemoryStorage()
Adding items to storage creates an update, that may be animated by storage delegate.
// section 0 is implied
storage.addItem(model)
storage.addItem(model, toSection: 0)
// section 0 is implied
storage.addItems([model1,model2])
storage.addItems([model1,model2], toSection:0)
Setting items creates an update, that requires storage delegate to reload it's UI. Essentially, it leads to UICollectionView.reloadData
or UITableView.reloadData
.
// section 0 is implied
storage.setItems([1,2,3])
storage.setItems([4,5,6], forSection: 1)
// 1,2,3 - section 0, 4,5,6 - section 1
storage.setItemsForAllSections([[1,2,3],[4,5,6]])
Inserting items creates an update, that may be animated by storage delegate.
try? storage.insertItem(model, to: indexPath)
// Inserts items starting at provided indexPath.
storage.insertItems([1,2,3], at: IndexPath(item: 3, section:0))
// Inserts items at provided indexPaths.
storage.insertItems([1,2], to: [IndexPath(item:3, section: 0), IndexPath(item: 4, section: 0)])
Removing / replacing/ reloading items creates an update, that may be animated by storage delegate.
// Items need to conform to `Equatable` protocol
try? storage.removeItem(model)
// Items need to conform to `Equatable` protocol
storage.removeItems([model1,model2])
storage.removeItems(at: indexPaths)
storage.removeItems(fromSection: 1)
// Causes `reloadData`
storage.removeAllItems()
// Item need to conform to `Equatable` protocol
try? storage.replaceItem(model1, with: model2)
// Causes storage update with reload animation, if available
storage.reloadItem(model1)
// Animated move
storage.moveItem(at: IndexPath(item:0, section:0), to: IndexPath(item:0, section:1))
// Without animations - useful for datasource only update, such as after drag&drop or reordering, where UI was already updated.
storage.moveItemWithoutAnimation(from: IndexPath(item:0, section:0), to: IndexPath(item:0, section:1))
Deleting / moving / inserting sections creates an update, that may be animated by storage delegate.
storage.deleteSections(IndexSet(integer: 1))
storage.moveSection(1, toSection: 3)
// Reloads data
storage.setSection(SectionModel(), forSection: 1)
// Animated insertion
storage.insertSection(SectionModel(), atIndex: 1)
If you need to perform several animated changes to datasource simultaneously, you can use performUpdates
method:
storage.performUpdates {
storage.addItems([2,4,6])
try? storage.insertItem(3, to: indexPath(1, 0))
}
Those changes will produce a single StorageUpdate
instance, thus allowing UITableView
or UICollectionView
to animate changes in a single batch update.
Warning. Performing mutually exclusive updates inside block can cause application crash. For example adding and removing the same item may crash
UICollectionView
.
let item = storage.item(at: IndexPath(item:1, section:0)
let indexPath = storage.indexPath(forItem:model)
let itemsInSection = storage.items(inSection:0)
let section = storage.section(atIndex:0)
Sometimes you may need to update batch of sections, remove all items, and add new ones. For those massive updates you don't actually need to update interface until update is finished. Wrap your updates in single block and pass it to updateWithoutAnimations method:
storage.updateWithoutAnimations {
// Add multiple rows, or another batch of edits
}
// Calling reloadData is mandatory after calling this method, or you will get crash at runtime.