{"id":21824387,"url":"https://github.com/shopify/functionaltabledata","last_synced_at":"2025-04-05T05:08:21.528Z","repository":{"id":46242134,"uuid":"98907583","full_name":"Shopify/FunctionalTableData","owner":"Shopify","description":"Declarative UITableViewDataSource implementation","archived":false,"fork":false,"pushed_at":"2024-04-09T14:17:55.000Z","size":2064,"stargazers_count":366,"open_issues_count":11,"forks_count":30,"subscribers_count":414,"default_branch":"main","last_synced_at":"2025-04-05T05:08:13.396Z","etag":null,"topics":["declarative","functional-programming","ios","swift","uicollectionview","uitableview","user-interface"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shopify.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2017-07-31T16:07:49.000Z","updated_at":"2025-01-03T11:09:03.000Z","dependencies_parsed_at":"2024-04-17T03:06:16.016Z","dependency_job_id":"248261c5-393d-4997-b192-a43611dbcfa0","html_url":"https://github.com/Shopify/FunctionalTableData","commit_stats":{"total_commits":267,"total_committers":37,"mean_commits":7.216216216216216,"dds":0.7378277153558053,"last_synced_commit":"00f980c613b64464f4ccaa0e183a5331ed94c00b"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2FFunctionalTableData","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2FFunctionalTableData/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2FFunctionalTableData/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2FFunctionalTableData/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shopify","download_url":"https://codeload.github.com/Shopify/FunctionalTableData/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289428,"owners_count":20914464,"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":["declarative","functional-programming","ios","swift","uicollectionview","uitableview","user-interface"],"created_at":"2024-11-27T17:57:54.189Z","updated_at":"2025-04-05T05:08:21.495Z","avatar_url":"https://github.com/Shopify.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://github.com/Shopify/FunctionalTableData/raw/main/Images/Banner.png\" /\u003e\n\nFunctional Table Data implements a functional renderer for UITableView. You pass it a complete description of your table state, and Functional Table Data compares it with the previous render call to insert, update, and remove the sections and cells that have changed. This massively simplifies state management of complex UI.\n\nNo longer do you have to manually track the number of sections, cells, and indices of your UI. Build one method that generates your table state structure from your data. The provided `HostCell` generic makes it easy to add FunctionalTableData support to `UITableViewCell`s.\n\n|         | Noteworthy features       |\n----------|---------------------\n💯 | Functional approach for maintaining table state\n👷‍ | Reusable views and states\n✅ | Unit tests\n🔀 | Automatic diff in your states\n❤️ | Used across Shopify's iOS apps\n🙅 | No more IndexPath bookkeeping\n\n## Installation\n\n### Manual\n\nSimply drag and drop `FunctionalTableData/FunctionalTableData.xcodeproj` into your Xcode project.\n\n### Swift Package Manager (SPM)\n\nAdd `https://github.com/Shopify/FunctionalTableData` to your package dependencies.\n\n### Carthage\n\nAdd the following to your `Cartfile`:\n\n```ruby\ngithub \"Shopify/FunctionalTableData\"\n```\n\n## Getting started\nTo use the Functional Table Data (FTD) two things are required, one instance of UITableView, and an instance of the FTD itself. Once both are available, typically in a view controller's `viewDidLoad`, they are connected together using\n`functionalTableData.tableView = yourTableViewInstance`. After this, every time we want to display/update the data we simply call `functionalTableData.renderAndDiff(sections)`.\n\nFor more information, read our [documentation](https://shopify.github.io/FunctionalTableData/).\n\n## Usage\n\nAny time you want to update the data currently being displayed you generate the new state and pass it off to your instance of the Functional Table Data. The FTD is then responsible for computing the differences between the previous state and the next state and updating itself as necessary.\n\nThe `FunctionalTableData` holds onto an array of sections where each section has a key. This key must be unique across all sections but should be deterministic so that it's possible to adjust the rows contained within that section without replacing the entire section itself.\n\n```swift\nlet section = TableSection(key: \"header-unique-key\", rows: [])\n```\n\nEach section contains a series of rows where each row value must conform to the `CellConfigType` protocol.\n\n```swift\n/// The simplest possible version of a cell that displays a label.\n/// Useful to get started, but in most cases a more robust state should be used allowing more customization.\ntypealias LabelCell = HostCell\u003cUILabel, String, LayoutMarginsTableItemLayout\u003e\n\nlet cells: [CellConfigType] = [\n\tLabelCell(key: \"company\", state: \"Shopify\") { view, state in\n\t\tview.text = state\n\t},\n\tLabelCell(key: \"location\", state: \"🇨🇦\") { view, state in\n\t\tview.text = state\n\t}\n]\n```\n\nThe rows themselves also have a key which must be unique inside of that section. This key is used to determine when new rows are added to a section, if any were removed, or if any moved to a different location.\nAdditionally, each `CellConfig` type implements an isEqual function to determine if two of them represent the same data being displayed. This allows for a single cell to perform a state change operation, that is, a toggle changing from its `off` to `on` state, a text value changing, etc.\n\nAfter assigning the variable `rows` to our previously created `section`, all that is needed to display the data in the table view is this method.\n\n```swift\nfunctionalTableData.renderAndDiff([section])\n```\n\n\u003cimg src=\"https://github.com/Shopify/FunctionalTableData/raw/main/Images/Example1.png\" /\u003e\n\n### Building new Cells\nKnowing that a cell consists of a view and state let's start with a simple example, a cell that displays a label. By specifying the generic requirements of `HostCell`, the simplest possible example is one that takes an `UILabel` as its view, a `String` as its state and `LayoutMarginsTableItemLayout` as the layout (See `TableItemLayout` for more info).\n\n```swift\ntypealias LabelCell = HostCell\u003cUILabel, String, LayoutMarginsTableItemLayout\u003e\n\n// Usage\nLabelCell(key: \"company\", state: \"Shopify\") { view, state in\n\tview.text = state\n}\n```\n\nAlthough, the previous code is very useful to get started, in most cases a more robust state should be used allowing more customization. A better example would be something like this\n\n```swift\ntypealias LabelCell = HostCell\u003cUILabel, LabelState, LayoutMarginsTableItemLayout\u003e\n\nstruct LabelState: Equatable {\n\tlet text: String\n\tlet alignment: NSTextAlignment\n\tlet color: UIColor\n\n\tstatic func ==(lhs: LabelState, rhs: LabelState) -\u003e Bool {\n\t\treturn lhs.text == rhs.text \u0026\u0026 lhs.alignment == rhs.alignment \u0026\u0026 lhs.color == rhs.color\n\t}\n}\n\n// Usage\nLabelCell(key: \"company\", state: LabelState(text: \"Shopify\",\n                                            alignment: .center,\n                                            color: .green)) { view, state in\n\tguard let state = state else {\n\t\t// If the state is `nil`, prepare this view to be reused\n\t\tview.text = \"\"\n\t\tview.textAlignment = .natural\n\t\tview.textColor = .black\n\t\treturn\n\t}\n\tview.text = state.text\n\tview.textAlignment = state.alignment\n\tview.textColor = state.color\n}\n```\n\nAt the end of the day `HostCell` is just one of the possible implementations of `CellConfigType`, that's the underlying power of this framework.\n\n## Other resources\n\n- [Building Apps with FunctionalTableData](https://medium.com/@raulriera/building-apps-with-functionaltabledata-c99bfaa7e2e5).\n- [FunctionalTableData and Interface Builder 🎨✨](https://medium.com/@raulriera/using-interface-builder-and-code-%EF%B8%8F-d9db30269d1d).\n\nSeen other articles in the wild? Feel free to open a [pull request](https://github.com/Shopify/FunctionalTableData/pulls).\n\n## License\nFunctional Table Data is under the [MIT License](https://github.com/Shopify/FunctionalTableData/blob/main/LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshopify%2Ffunctionaltabledata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshopify%2Ffunctionaltabledata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshopify%2Ffunctionaltabledata/lists"}