Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/FluidGroup/DataSources
💾 🔜📱 Type-safe data-driven CollectionView, TableView Framework. (We can also use ASCollectionNode)
https://github.com/FluidGroup/DataSources
collectionview data-driven datasource diff ios rxswift uicollectionview viewcontroller
Last synced: 15 days ago
JSON representation
💾 🔜📱 Type-safe data-driven CollectionView, TableView Framework. (We can also use ASCollectionNode)
- Host: GitHub
- URL: https://github.com/FluidGroup/DataSources
- Owner: FluidGroup
- License: mit
- Created: 2017-08-07T18:48:18.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2024-03-17T15:03:29.000Z (9 months ago)
- Last Synced: 2024-04-15T01:19:07.842Z (8 months ago)
- Topics: collectionview, data-driven, datasource, diff, ios, rxswift, uicollectionview, viewcontroller
- Language: Swift
- Homepage:
- Size: 4.51 MB
- Stars: 567
- Watchers: 10
- Forks: 30
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
- awesome-ios - DataSources - Type-safe data-driven List-UI Framework. (We can also use ASCollectionNode) (UI / Table View / Collection View)
README
# DataSources
💾 🔜📱 Type-safe data-driven List-UI Framework. (We can also use ASCollectionNode)Partial updates(insert, delete, move) of UICollectionView/UITableView is important things for fancy UI.
But, It's hard that synchronous of data and UI.
**DataSources** will solve this problem.![](https://img.shields.io/badge/Swift-3.1-blue.svg?style=flat)
[![CI Status](http://img.shields.io/travis/muukii/DataSources.svg?style=flat)](https://travis-ci.org/muukii/DataSources)
[![Version](https://img.shields.io/cocoapods/v/DataSources.svg?style=flat)](http://cocoapods.org/pods/DataSources)
[![License](https://img.shields.io/cocoapods/l/DataSources.svg?style=flat)](http://cocoapods.org/pods/DataSources)
[![Platform](https://img.shields.io/cocoapods/p/DataSources.svg?style=flat)](http://cocoapods.org/pods/DataSources)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmuukii%2FDataSources.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmuukii%2FDataSources?ref=badge_shield)![](sample.gif)
## Thanks
**Diff-algorithm**
- Inspired by IGListKit/IGListDiff.
- https://github.com/Instagram/IGListKit
- https://github.com/lxcid/ListDiff
## Features- Data driven update
- Data did change, then will display.
- Partial updates, no more calling `reloadData`
- Smooth and Faster.
- if the count of changes larger than 300, update with non-animation.
- Simplified usage
- We can use different type each section.
- Type-safe
- We can take clearly typed object by IndexPath.
- Using Adapter-pattern for List-UI
- For example, We can also use this for ASCollectionNode of Texture. (Demo app includes it)
- Reorder by UI operation
- This library is not supported moving between section.## Requirements
- Swift 4
- iOS 9+## Usage (Example)
### Conform protocol `Diffable`
```swift
public protocol Diffable {
associatedtype Identifier : Hashable
var diffIdentifier: Identifier { get }
}
``````swift
struct Model : Diffable {var diffIdentifier: String {
return id
}
let id: String
}
```### 🤠Most Simplified Usage
1. Define `SectionDataController` in ViewController
```swift
let collectionView: UICollectionViewlet sectionDataController = SectionDataController(
adapter: CollectionViewAdapter(collectionView: self.collectionView),
isEqual: { $0.id == $1.id } // If Model has Equatable, you can omit this closure.
)var models: [Model] = [] {
didSet {
sectionDataController.update(items: items, updateMode: .partial(animated: true), completion: {
// Completed update
})
}
}let dataSource = CollectionViewDataSource(sectionDataController: sectionDataController)
dataSource.cellFactory = { _, collectionView, indexPath, model in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.label.text = model.title
return cell
}collectionView.dataSource = dataSource
```### 😎 Semi Manual
#### Single-Section (UICollectionView)
1. Define `SectionDataController` in ViewController
```swift
let collectionView: UICollectionView
var models: [Model]let sectionDataController = SectionDataController(
adapter: CollectionViewAdapter(collectionView: self.collectionView),
isEqual: { $0.id == $1.id } // If Model has Equatable, you can omit this closure.
)
```2. Bind Models to `SectionDataController` in ViewController
```swift
var models: [Model] = […] {
didSet {
sectionDataController.update(items: items, updateMode: .partial(animated: true), completion: {
// Completed update
})
}
}
```3. Implement UICollectionViewDataSource in ViewController
```swift
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return sectionDataController.numberOfItems()
}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
let m = sectionDataController.item(for: indexPath)
cell.label.text = m.title
return cell
}
```#### Multiple-Section (UICollectionView)
1. Define `DataController` in ViewController
```swift
let collectionView: UICollectionView
var models: [Model]let dataController = DataController(adapter: CollectionViewAdapter(collectionView: self.collectionView))
```2. Define `Section` in ViewController
```swift
let section0 = Section(ModelA.self, isEqual: { $0.id == $1.id })
let section1 = Section(ModelB.self, isEqual: { $0.id == $1.id })
```3. Add `Section` to `DataController`
Order of Section will be decided in the order of addition.
```swift
dataController.add(section: section0) // will be 0 of section
dataController.add(section: section1) // will be 1 of section
```4. Bind Models to DataController
```swift
var section0Models: [ModelA] = […] {
didSet {
dataController.update(
in: section0,
items: section0Models,
updateMode: .partial(animated: true),
completion: {
})
}
}var section1Models: [ModelA] = […] {
didSet {
dataController.update(
in: section1,
items: section1Models,
updateMode: .partial(animated: true),
completion: {
})
}
}
```5. Implement UICollectionViewDataSource
```swift
func numberOfSections(in collectionView: UICollectionView) -> Int {
return dataController.numberOfSections()
}func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataController.numberOfItems(in: section)
}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return dataController.item(
at: indexPath,
handlers: [
.init(section: section0) { (m: ModelA) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.label.text = m.title
return cell
},
.init(section: section1) { (m: ModelB) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.label.text = m.title
return cell
},
])/* Other way
switch indexPath.section {
case section0:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
let m = _dataController.item(at: indexPath, in: section0)
cell.label.text = m.title
return cell
case section1:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
let m = _dataController.item(at: indexPath, in: section1)
cell.label.text = m.title
return cell
default:
fatalError()
}
*/
}
```## Reorder by UI operation
`SectionDataController` has a snapshot for `List-UI`.
It helps that perform batch update List-UI in safety.But, the snapshots include side-effects.
For example, if we did reorder items of `List-UI` by UI operation.
In this time, Items of List-UI is caused differences to the snapshot.
It will be caused unnecessary diff.Therefore when we reorder items, we should operation followings.
0. Reorder items of UI
1. Call `SectionDataController.reserveMoved(...`
2. Reorder items of Array
3. Call `SectionDataController.update(items: [T]..`# Demo Application
This repository include Demo-Application.
You can touch DataSources.1. Clone repository.
```
$ git clone https://github.com/muukii/DataSources.git
$ cd DataSources
$ pod install
```2. Open xcworkspace
3. Run `DataSourcesDemo` on iPhone Simulator.# Author
muukii, [email protected], https://muukii.me/
# License
**DataSources** is available under the MIT license. See the LICENSE file for more info.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmuukii%2FDataSources.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmuukii%2FDataSources?ref=badge_large)