{"id":2886,"url":"https://github.com/ra1028/Carbon","last_synced_at":"2025-08-06T16:31:18.070Z","repository":{"id":34128260,"uuid":"164695859","full_name":"ra1028/Carbon","owner":"ra1028","description":"🚴 A declarative library for building component-based user interfaces in UITableView and UICollectionView.","archived":false,"fork":false,"pushed_at":"2024-07-13T10:04:33.000Z","size":13361,"stargazers_count":1335,"open_issues_count":10,"forks_count":97,"subscribers_count":25,"default_branch":"master","last_synced_at":"2024-12-05T09:49:52.206Z","etag":null,"topics":["component","datasource","declarative","delegate","differencekit","diffing","functionbuilder","ios","node","react","render","swift","swiftui","uicollectionview","uitableview"],"latest_commit_sha":null,"homepage":"https://ra1028.github.io/Carbon","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ra1028.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-08T17:03:43.000Z","updated_at":"2024-11-27T00:10:36.000Z","dependencies_parsed_at":"2024-09-30T11:11:01.462Z","dependency_job_id":null,"html_url":"https://github.com/ra1028/Carbon","commit_stats":{"total_commits":139,"total_committers":4,"mean_commits":34.75,"dds":0.02877697841726623,"last_synced_commit":"9e572593e02ce77e54932d46d130054a13e2a056"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FCarbon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FCarbon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FCarbon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FCarbon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ra1028","download_url":"https://codeload.github.com/ra1028/Carbon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228923690,"owners_count":17992566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","datasource","declarative","delegate","differencekit","diffing","functionbuilder","ios","node","react","render","swift","swiftui","uicollectionview","uitableview"],"created_at":"2024-01-05T20:16:25.450Z","updated_at":"2024-12-09T16:31:01.204Z","avatar_url":"https://github.com/ra1028.png","language":"Swift","readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/ra1028/Carbon/master/assets/logo/png/logo_carbon_bnr3_white.png\" width=700\u003e\n\u003c/p\u003e\n\n\u003cH4 align=\"center\"\u003e\nA declarative library for building component-based user interfaces\u003c/br\u003e\nin UITableView and UICollectionView.\u003c/br\u003e\n\u003c/H4\u003e\n\n|Declarative|Component-Based|Non-Destructive|\n|:----------|:--------------|:--------------|\n|Provides a declarative design with power of diffing algorithm for building list UIs.|Declare component once, it can be reused regardless kind of the list element.|Solves the various problems by architecture and algorithm without destructing UIKit.|\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/ra1028/Carbon/releases/latest\"\u003e\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/release/ra1028/Carbon.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/Carbon\"\u003e\u003cimg alt=\"CocoaPods\" src=\"https://img.shields.io/cocoapods/v/Carbon.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\u003cimg alt=\"Carthage\" src=\"https://img.shields.io/badge/carthage-compatible-yellow.svg\"/\u003e\u003c/a\u003e\n\u003c/br\u003e\n\u003ca href=\"https://github.com/ra1028/Carbon/actions\"\u003e\u003cimg alt=\"CI Status\" src=\"https://github.com/ra1028/Carbon/workflows/GitHub%20Actions/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg alt=\"Swift 5.1\" src=\"https://img.shields.io/badge/language-Swift 5.1-orange.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://developer.apple.com/\"\u003e\u003cimg alt=\"Platform\" src=\"https://img.shields.io/badge/platform-iOS-green.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/ra1028/Carbon/blob/master/LICENSE\"\u003e\u003cimg alt=\"Lincense\" src=\"https://img.shields.io/badge/License-Apache%202.0-black.svg\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Introduction\n\nCarbon is a library for building component-based user interfaces in UITableView and UICollectionView inspired by [SwiftUI](https://developer.apple.com/xcode/swiftui) and [React](https://reactjs.org).  \nThis make it painless to build and maintain the complex UIs.  \nSince components made with `Carbon` can be works directly on `SwiftUI`, the cost of future migration can be greatly reduced.  \n\nUses [DifferenceKit](https://github.com/ra1028/DifferenceKit) which is highly optimized based on Paul Heckel's paper for diffing.  \nDeclarative design and diffing algorithm make your code more predictable, debugging easier and providing beautiful animations to users.  \n\nOur goal is similar to [Instagram/IGListKit](https://github.com/Instagram/IGListKit) and [airbnb/Epoxy](https://github.com/airbnb/epoxy), we respect those library as pioneers.  \n\n---\n\n## Examples\n\n|![Pangram](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/pangram.gif)|![Kyoto](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/kyoto.gif)|![Emoji](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/emoji.gif)|![Todo](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/todo.gif)|![Form](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/form.gif)|\n|:----------------------------:|:------------------------:|:------------------------:|:----------------------:|:----------------------:|\n\n---\n\n\u003cimg src=\"https://raw.githubusercontent.com/ra1028/Carbon/master/assets/hello.png\" height=240 align=right\u003e\n\n```swift\nrenderer.render {\n    Header(\"GREET\")\n        .identified(by: \\.title)\n\n    HelloMessage(\"Vincent\")\n    HelloMessage(\"Jules\")\n    HelloMessage(\"Mia\")\n\n    Footer(\"👋 Greeting from Carbon\")\n        .identified(by: \\.text)\n}\n```\n\n---\n\n### [SwiftUI Compatibility](https://github.com/ra1028/Carbon#swiftui-compatibility-1)\n\n```swift\nstruct ContentView: View {\n    var body: some View {\n        ScrollView {\n            VStack {\n                Text(\"GREET\")\n                    .font(.title)\n                    .padding(.horizontal, 16)\n\n                HelloMessage(\"World\")\n                    .frame(height: 60)\n                    .background(Color.red)\n            }\n        }\n    }\n}\n```\n\n---\n\n## Getting Started\n\n- [API Documentation](https://ra1028.github.io/Carbon)\n- [Example Apps](https://github.com/ra1028/Carbon/tree/master/Examples)\n- [Playground](https://github.com/ra1028/Carbon/blob/master/Carbon.playground/Contents.swift)\n\n### Build for Development\n\n```sh\n$ git clone https://github.com/ra1028/Carbon.git\n$ cd Carbon/\n$ make setup\n$ open Carbon.xcworkspace\n```\n\n---\n\n## Basic Usage\n\nDescribed here are the fundamentals for building list UIs with Carbon.  \n[The API document](https://ra1028.github.io/Carbon) will help you understand the details of each type.  \nFor more advanced usage, see the [Advanced Guide](https://github.com/ra1028/Carbon#advanced-guide).  \nAnd the more practical examples are [here](https://github.com/ra1028/Carbon/tree/master/Examples).  \n\n### Component\n\n`Component` is the base unit of the UI in Carbon.  \nAll elements are made up of components, and it can be animated by diffing update.  \n\n`UIView`, `UIViewController` and its subclasses are available as `content` of component by default.  \nYou can declare fixed size component by implementing `referenceSize(in bounds: CGRect) -\u003e CGSize?`. The default is to return nil and falls back to a value such as `UITableView.rowHeight` or `UICollectionViewFlowLayout.itemSize`.  \nSee [here](https://github.com/ra1028/Carbon#component-in-depth) for more depth of component.\n\nDefinition below is the simplest implementation.  \n\n```swift\nstruct HelloMessage: Component {\n    var name: String\n\n    func renderContent() -\u003e UILabel {\n        UILabel()\n    }\n\n    func render(in content: UILabel) {\n        content.text = \"Hello \\(name)\"\n    }\n}\n```\n\nComponent used as a cell requires to specify an arbitrary `id`.  \nGive an `id` by `Component.identified(by:)` or declare it by using [`IdentifiableComponent`](https://github.com/ra1028/Carbon#identifiablecomponent) protocol.\n\n### Renderer\n\nThe components are displayed on the list UI by `Renderer.render`.  \nBoilerplates such as registering element types to a table view are no longer needed in Carbon.  \n\nThe adapter acts as delegate and dataSource, the updater handles updates.  \nYou can also change the behaviors by inheriting and customizing it.  \nThere are also `UITableViewReloadDataUpdater` and `UICollectionViewReloadDataUpdater` which update by `reloadData` without diffing updates.  \n\nWhen `render` called again, the updater calculates the diff from the currently rendered components and updates them with the system animation.  \n\nRenderer for UITableView:\n```swift\n@IBOutlet var tableView: UITableView!\n\nlet renderer = Renderer(\n    adapter: UITableViewAdapter(),\n    updater: UITableViewUpdater()\n)\n\noverride func viewDidLoad() {\n    super.viewDidLoad()\n\n    renderer.target = tableView\n}\n```\n\nRenderer for UICollectionView:\n```swift\n@IBOutlet var collectionView: UICollectionView!\n\nlet renderer = Renderer(\n    adapter: UICollectionViewFlowLayoutAdapter(),\n    updater: UICollectionViewUpdater()\n)\n\noverride func viewDidLoad() {\n    super.viewDidLoad()\n\n    renderer.target = collectionView\n}\n```\n\nRender Components:\n```swift\nrenderer.render {\n    Header(\"GREET\")\n        .identified(by: \\.title)\n\n    HelloMessage(\"Butch\")\n    HelloMessage(\"Fabianne\")\n}\n```\n\n### Section\n\nA section can include header, footer and cells.  \nThis also needs to specify `id` for identify from among multiple sections.  \nThe cells can be declared using a function builder as below:\n\n```swift\nlet appearsBottomSection: Bool = ...\nlet appearsFourthMan: Bool = ...\n\nrenderer.render {\n    Section(\n        id: \"Bottom\",\n        header: Header(\"GREET\"),\n        footer: Footer(\"👋 Greeting from Carbon\"),\n        cells: {\n            HelloMessage(\"Marsellus\")\n            HelloMessage(\"The Wolf\")\n        }\n    )\n\n    if appearsBottomSection {\n        Section(id: \"Top\") {\n            HelloMessage(\"Brett\")\n            HelloMessage(\"Roger\")\n\n            if appearsFourthMan {\n                HelloMessage(\"Fourth Man\")\n            }\n        }\n    }\n}\n```\n\n### Group\n\nThe number of limit to declare cells or section with function builder syntax is until `10`. You can avoid that limitation by grouping with `Group`.  \nIt can also be used to create a cell or section from an array with N elements.  \n\nGroup of Components:\n```swift\nrenderer.render {\n    Group {\n        Header(\"GREET\")\n            .identified(by: \\.title)\n\n        HelloMessage(\"Vincent\")\n        HelloMessage(\"Jules\")\n    }\n\n    Group(of: [\"Pumpkin\", \"Honey Bunny\"]) { name in\n        HelloMessage(name)\n    }\n}\n```\n\nGroup of Sections:\n```swift\nrenderer.render {\n    Group {\n        Section(id: 0) {\n            HelloMessage(\"Jimmie\")\n        }\n\n        Section(id: 1) {\n            HelloMessage(\"Bonnie\")\n        }\n    }\n\n    Group(of: [\"Lance\", \"Jody\"]) { name in\n        Section(id: name) {\n            HelloMessage(name)\n        }\n    }\n}\n```\n\n\u003cH3 align=\"center\"\u003e\n\u003ca href=\"https://ra1028.github.io/Carbon\"\u003e[See More Usage]\u003c/a\u003e\n\u003ca href=\"https://github.com/ra1028/Carbon/tree/master/Examples/Example-iOS\"\u003e[See Example App]\u003c/a\u003e\n\u003c/H3\u003e\n\n---\n\n## Advanced Guide\n\n### Custom Content\n\nOf course, the content of component can use custom class. You can also instantiate it from Xib.  \nIt can be inherited whichever class, but the common means is inherit `UIView` or `UIViewController`.  \n\n\u003cimg src=\"https://raw.githubusercontent.com/ra1028/Carbon/master/assets/content-xib.png\" height=90 align=right\u003e\n\n```swift\nclass HelloMessageContent: UIView {\n    @IBOutlet var label: UILabel!\n}\n```\n\n``` swift\nstruct HelloMessage: Component {\n    var name: String\n\n    func renderContent() -\u003e HelloMessageContent {\n        HelloMessageContent.loadFromNib()  // Extension for instantiate from Xib. Not in Carbon.\n    }\n\n    func render(in content: HelloMessageContent) {\n        content.label.text = \"Hello \\(name)\"\n    }\n}\n```\n\n### IdentifiableComponent\n\n`IdentifiableComponent` is a component that simply can predefine an identifier.  \nIt can be omitted the definition of `id` if the component conforms to `Hashable`.  \n\n```swift\nstruct HelloMessage: IdentifiableComponent {\n    var name: String\n\n    var id: String {\n        name\n    }\n\n    ...\n```\n\n### SwiftUI Compatibility\n\nComponents made with `Carbon` are compatible with `SwiftUI`.  \nThe component can easily works as SwiftUI by composing with `View` protocol.  \nCurrently SwiftUI doesn't support self-sizing, so can use `UIView.intrinsicContentSize` or specify the height explicitly by `Component.referenceSize(in:)` or `View.frame(height:)`.  \n\n```swift\nstruct HelloMessage: Component, View {\n    ...\n}\n```\n\n```swift\nstruct ContentView: View {\n    var body: some View {\n        VStack(alignment: .leading) {\n            Text(\"GREET\")\n\n            HelloMessage(\"World\")\n                .frame(height: 60)\n\n            Spacer()\n        }\n    }\n}\n```\n\n### Component in-Depth\n\nComponents can define more detailed behaviors.  \nFollowing are part of it.  \n\n- **shouldContentUpdate(with next: Self) -\u003e Bool**  \nIf the result is `true`, the component displayed as a cell is reloaded individually, header or footer is reloaded with entire section.  \nBy default it returns `false`, but the updater will always re-render visible components changed.  \n\n- **referenceSize(in bounds: CGRect) -\u003e CGSize?**  \nDefining the size of component on the list UI.  \nYou can use default value such as `UITableView.rowHeight` or `UICollectionViewLayout.itemSize` by returning `nil`.  \nReturns `nil` by default.  \n\n- **shouldRender(next: Self, in content: Content) -\u003e Bool**  \nBy returning `false`, you can skip component re-rendering when reloading or dequeuing element.  \nInstead of re-rendering, detects component changes by comparing with next value.  \nThis is recommended to use only for performance tuning.  \n\n- **contentWillDisplay(_ content: Content)**  \nInvoked every time of before a component got into visible area.  \n\n- **contentDidEndDisplay(_ content: Content)**  \nInvoked every time of after a component went out from visible area.  \n\n[See more](https://ra1028.github.io/Carbon/Protocols/Component.html)\n\n### Selection\n\nCell selection can be handled by setting `didSelect` to the instance of `UITableViewAdapter` or `UICollectionViewAdapter`.  \n\n```swift\nrenderer.adapter.didSelect { context in\n    print(context)\n}\n```\n\nHowever, we recommend to make the `Content` of the component to the class inherited from `UIControl`.  \nIt's more maintainable and extensible.  \n\n```swift\nclass MenuItemContent: UIControl {\n    @IBOutlet var label: UILabel!\n\n    var onSelect: (() -\u003e Void)?\n\n    @objc func handleSelect() {\n        onSelect?()\n    }\n\n    override func awakeFromNib() {\n        super.awakeFromNib()\n        addTarget(self, action: #selector(handleSelect), for: .touchUpInside)\n    }\n}\n```\n\n```swift\nstruct MenuItem: Component {\n    var text: String\n    var onSelect: () -\u003e Void\n\n    func renderContent() -\u003e MenuItemContent {\n        MenuItemContent.loadFromNib()\n    }\n\n    func render(in content: MenuItemContent) {\n        content.label.text = text\n        content.onSelect = onSelect\n    }\n}\n```\n\nIn this way, in order to cancel the selection by scrolling, you need to implement the following extension.  \n\n```swift\nextension UITableView {\n    open override func touchesShouldCancel(in view: UIView) -\u003e Bool {\n        true\n    }\n}\n\nextension UICollectionView {\n    open override func touchesShouldCancel(in view: UIView) -\u003e Bool {\n        true\n    }\n}\n```\n\n### Adapter Customization\n\nYou can add methods of `delegate`, `dataSource` by subclassing each adapter.  \n\n```swift\nclass CustomTableViewdapter: UITableViewAdapter {\n    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -\u003e String? {\n        \"Header title for section\\(section)\"\n    }\n}\n\nlet renderer = Renderer(\n    adapter: CustomTableViewAdapter(),\n    updater: UITableViewUpdater()\n)\n```\n\nFurthermore, it can be customized the class of the elements(cell/header/footer) which becomes the container of components by overriding some methods in adapter as following.  \nYou can also use `xib` by giving nib as parameter of init of the return value Registration.  \n\n```swift\nclass CustomTableViewAdapter: UITableViewAdapter {\n    // Use custom cell.\n    override func cellRegistration(tableView: UITableView, indexPath: IndexPath, node: CellNode) -\u003e CellRegistration {\n        CellRegistration(class: CustomTableViewCell.self)\n    }\n\n    // Use custom header view.\n    override func headerViewRegistration(tableView: UITableView, section: Int, node: ViewNode) -\u003e ViewRegistration {\n        ViewRegistration(class: CustomTableViewHeaderFooterView.self)\n    }\n\n    // Use custom footer view.\n    override func footerViewRegistration(tableView: UITableView, section: Int, node: ViewNode) -\u003e ViewRegistration {\n        ViewRegistration(class: CustomTableViewHeaderFooterView.self)\n    }\n}\n```\n\nIn UICollectionViewAdapter, you can select the node corresponding to a certain kind.  \n\n```swift\nclass CustomCollectionViewAdapter: UICollectionViewAdapter {\n    override func supplementaryViewNode(forElementKind kind: String, collectionView: UICollectionView, at indexPath: IndexPath) -\u003e ViewNode? {\n        switch kind {\n        case \"CustomSupplementaryViewKindSectionHeader\":\n            return headerNode(in: indexPath.section)\n\n        default:\n            return super.supplementaryViewNode(forElementKind: kind, collectionView: collectionView, at: indexPath)\n        }\n    }\n}\n```\n\n[See more](https://ra1028.github.io/Carbon/Adapter.html)\n\n### Updater Customization\n\nIt can be modify the updating behavior of the list UI by inheriting `Updater`.  \nThis is important thing to make Carbon well adapted to your project.  \nBelow are some of the default provided settings of `updater`.  \n\n- **isAnimationEnabled**  \nIndicating whether enables animation for diffing updates, setting `false` will perform it using `UIView.performWithoutAnimation`.  \nDefault is `true`.  \n\n- **isAnimationEnabledWhileScrolling**  \nIndicating whether enables animation for diffing updates while target is scrolling, setting `false` will perform it  using `UIView.performWithoutAnimation`.  \nDefault is `false`.  \n\n- **animatableChangeCount**  \nThe max number of changes to perform diffing updates. It falls back to `reloadData` if it exceeded.  \nDefault is `300`.  \n\n- **keepsContentOffset**  \nIndicating whether that to reset content offset after updated.  \nThe content offset become unintended position after diffing updates in some case.\n If set `true`, revert content offset after updates.  \nDefault is `true`.  \n\n[See more](https://ra1028.github.io/Carbon/Updater.html)\n\n### Without FunctionBuilder Syntax\n\nCarbon can also build a UI with declarative syntax without function builder as following.  \n\n- **ViewNode**\n\nThis is a node representing header or footer. The node is wrap an instance of type conforming to `Component` protocol.  \n\n```swift\nViewNode(Header(\"GREET\"))\n```\n\n- **CellNode**\n\n`CellNode` is a node representing cell.  \nUnlike in the ViewNode, this needs an `id` which `Hashable` type to identify from among a lot of cells.  \nThe `id` is used to find the same component in the list data before and after changed.  \n\n```swift\nCellNode(id: 0, HelloMessage(\"Jules\"))\nCellNode(HelloMessage(\"Jules\").identified(by: \\.name))\nCellNode(HelloMessage(\"Jules\"))  // Using `IdentifiableComponent`.\n```\n\n- **Section** and render\n\n```swift\nrenderer.render(\n    Section(\n        id: \"Section\",\n        header: ViewNode(Header(\"GREET\")),\n        cells: [\n            CellNode(HelloMessage(\"Vincent\")),\n            CellNode(HelloMessage(\"Mia\")),\n            CellNode(HelloMessage(\"Jules\"))\n        ],\n        footer: ViewNode(Footer(\"👋 Greeting from Carbon\"))\n    )\n)\n```\n\n[See more](https://ra1028.github.io/Carbon/Node.html)\n\n---\n\n## Requirements\n\n- Swift 5.1+\n- Xcode 11.0+\n\n---\n\n## Installation\n\n### [CocoaPods](https://cocoapods.org)\nAdd the following to your `Podfile`:\n```ruby\npod 'Carbon'\n```\n\n### [Carthage](https://github.com/Carthage/Carthage)\nAdd the following to your `Cartfile`:\n```\ngithub \"ra1028/Carbon\"\n```\n\n### [Swift Package Manager](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app)\nSelect Xcode menu `File \u003e Swift Packages \u003e Add Package Dependency...` and enter repository URL with GUI.\n```\nRepository: https://github.com/ra1028/Carbon\n```\n\n---\n\n## Contributing\n\nPull requests, bug reports and feature requests are welcome 🚀  \nPlease see the [CONTRIBUTING](https://github.com/ra1028/Carbon/blob/master/CONTRIBUTING.md) file for learn how to contribute to Carbon.  \n\n---\n\n## Respect\n\nLibraries for list UIs using diffing algorithm that I have sincerely ❤️ and respected.  \n\n- [React](https://github.com/facebook/react/) (by [Facebook](https://github.com/facebook))  \n  I have very inspired about paradigm and API design.  \n- [IGListKit](https://github.com/Instagram/IGListKit) (by [Instagram](https://github.com/Instagram))  \n  The most popular library among list UI libraries using diffing algorithm in iOS.  \n- [Epoxy](https://github.com/airbnb/epoxy) (by [Airbnb](https://github.com/airbnb))  \n  The most popular library among list UI libraries using diffing algorithm in Android.  \n- [RxDataSources](https://github.com/RxSwiftCommunity/RxDataSources) (by [@kzaher](https://github.com/kzaher), [RxSwift Community](https://github.com/RxSwiftCommunity))  \n  A great library that can complex diffing update by very fast algorithms.  \n- [Texture](https://github.com/TextureGroup/Texture) (by [TextureGroup](https://github.com/TextureGroup), [Facebook](https://github.com/facebook), [Pinterest](https://github.com/pinterest))  \n  The one and only library for creating list UIs that pursues rendering performance.  \n- [Bento](https://github.com/Babylonpartners/Bento) (by [Babylon Health](https://github.com/Babylonpartners))  \n  Bento is an awesome declarative library that has an API design which follows React.  \n- [ReactiveLists](https://github.com/plangrid/ReactiveLists) (by [PlanGrid](https://github.com/plangrid))  \n  Uses DifferenceKit as well as Carbon for the diffing algorithm.  \n\n---\n\n## License\n\nCarbon is released under the [Apache 2.0 License](https://github.com/ra1028/Carbon/blob/master/LICENSE).  \n\n---\n\n![Carbon Logo](https://raw.githubusercontent.com/ra1028/Carbon/master/assets/logo/png/logo_carbon_bnr1_white.png)\n","funding_links":[],"categories":["UI","Libs","Uncategorized","UI [🔝](#readme)","uitableview"],"sub_categories":["Table View / Collection View","UI","Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fra1028%2FCarbon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fra1028%2FCarbon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fra1028%2FCarbon/lists"}