{"id":2856,"url":"https://github.com/okcupid/OKTableViewLiaison","last_synced_at":"2025-08-06T16:31:58.576Z","repository":{"id":62449384,"uuid":"129934671","full_name":"OkCupid/OKTableViewLiaison","owner":"OkCupid","description":"Framework to help you better manage UITableViews","archived":false,"fork":false,"pushed_at":"2019-01-23T18:18:59.000Z","size":14895,"stargazers_count":85,"open_issues_count":0,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-09-14T11:49:27.101Z","etag":null,"topics":[],"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/OkCupid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-17T16:31:58.000Z","updated_at":"2024-01-03T09:01:24.000Z","dependencies_parsed_at":"2022-11-01T23:17:04.218Z","dependency_job_id":null,"html_url":"https://github.com/OkCupid/OKTableViewLiaison","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkCupid%2FOKTableViewLiaison","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkCupid%2FOKTableViewLiaison/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkCupid%2FOKTableViewLiaison/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkCupid%2FOKTableViewLiaison/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OkCupid","download_url":"https://codeload.github.com/OkCupid/OKTableViewLiaison/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228923735,"owners_count":17992570,"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":[],"created_at":"2024-01-05T20:16:24.632Z","updated_at":"2024-12-09T16:31:13.923Z","avatar_url":"https://github.com/OkCupid.png","language":"Swift","funding_links":[],"categories":["UI","Libs","UI [🔝](#readme)"],"sub_categories":["Table View / Collection View","UI"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/OkCupid/OKTableViewLiaison/master/Resources/logo.png\" width=500 /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://travis-ci.org/OkCupid/OKTableViewLiaison\"\u003e\n\u003cimg src=\"https://travis-ci.org/OkCupid/OKTableViewLiaison.svg?branch=master\u0026style=flat\"\nalt=\"Build Status\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/OKTableViewLiaison\"\u003e\n\u003cimg src=\"https://img.shields.io/cocoapods/v/OKTableViewLiaison.svg?style=flat\"\nalt=\"Pods Version\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n----------------\n\n`UITableView` made simple \u0026#128588;\n\n|         | Main Features  |\n----------|-----------------\n\u0026#128585; | Skip the `UITableViewDataSource` \u0026 `UITableViewDelegate` boilerplate and get right to building your `UITableView`!\n\u0026#127744; | Closure based API for section and row configuration\n\u0026#128196; | Built-in paging functionality\n\u0026#9989;   | Unit Tested\n\u0026#128036; | Written in Swift 4.2\n\n`OKTableViewLiaison` is 🔨 with \u0026#10084;\u0026#65039; by [📱 @ OkCupid](https://tech.okcupid.com).\nWe use the latest and greatest open source version of `master` in the OkCupid app.\n\n## Requirements\n\n- Xcode 10.0+\n- iOS 9.0+\n\n## Installation\n\n### CocoaPods\n\nThe preferred installation method is with [CocoaPods](https://cocoapods.org). Add the following to your `Podfile`:\n\n```ruby\npod 'OKTableViewLiaison'\n```\n\n## Example\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n## Usage\n`OKTableViewLiaison` allows you to more easily populate and manipulate `UITableView` rows and sections.\n\n### Getting Started\nTo get started, all you need to do is `liaise` an instance of `UITableView` to with a `OKTableViewLiaison`:\n\n```swift\nlet liaison = OKTableViewLiaison()\nlet tableView = UITableView()\n\nliaison.liaise(tableView: tableView)\n```\n\nBy liaising your tableView with the liaison, the liaison becomes its `UITableViewDataSource`, `UITableViewDelegate`, and `UITableViewDataSourcePrefetching`.\nIn the event you would like to remove the tableView from the liaison, simply invoke `liaison.detach()`.\n\nOKTableViewLiaison populates sections and rows using two main types:\n\n### Section\n`struct OKTableViewSection`\n\nTo create a section for our tableView, create an instance of `OKTableViewSection` and add it to the liaison.\n\n```swift\nlet section = OKTableViewSection()\n\nlet liaison = OKTableViewLiaison(sections: [section])\n```\nor\n\n```swift\nlet section = OKTableViewSection()\n\nliaison.append(section: section)\n```\n\n### Supplementary Section Views\nTo notify the liaison that your `OKTableViewSection` will display a header and/or footer view, you must provide an instance of `OKTableViewSectionComponentDisplayOption` during initialization.\n\n`OKTableViewSectionComponentDisplayOption` is an enumeration that notfies the liaison which supplementary views should be displayed for a given section. A header/footer view is represented by:\n\n`class OKTableViewSectionComponent\u003cView: UITableViewHeaderFooterView, Model\u003e`\n\n```swift\nlet header = OKTableViewSectionComponent\u003cUITableViewHeaderFooterView, User\u003e(.dylan)\nlet section = OKTableViewSection(componentDisplayOption: .header(component: header))\n```\n\nYou can set a static height of a section component by using either a CGFloat value or closure:\n\n```swift\nheader.set(height: .height, 55)\n\nheader.set(height: .height) { user -\u003e CGFloat in\n    return user.username == \"dylan\" ? 100 : 75\n}\n\nheader.set(height: .estimatedHeight, 125)\n```\n\nIn the event a height is not provided for a section component, the liaison will assume the supplementary view is self sizing and return a `.height` of `UITableView.automaticDimension`. Make sure you provide an `.estimatedHeight` to avoid layout complications.\n\nThe `OKTableViewSectionComponent ` views can be customized using `func set(command: OKTableViewSectionComponentCommand, with closure: @escaping (View, Model, Int) -\u003e Void)` at all the following lifecycle events:\n\n- configuration\n- didEndDisplaying\n- willDisplay\n\n```swift\nheader.set(command: .configuration) { view, user, section in\n    view.textLabel?.text = user.username\n}\n\nheader.set(command: .willDisplay) { view, user, section in\n    print(\"Header: \\(view) will display for Section: \\(section) with User: \\(user)\")\n}\n```\n\n### Rows\n`class OKTableViewRow\u003cCell: UITableViewCell, Model\u003e`\n\nTo add a row for a section, create an instance of `OKTableViewRow` and pass it to the initializer for a `OKTableViewSection` or if the row is added after instantiation you can perform that action via the liaison:\n\n```swift\nlet row = OKTableViewRow\u003cRowTableViewCell, RowModel\u003e(model: RowModel(type: .small))\nlet section = OKTableViewSection(rows: [row])\nliaison.append(section: section)\n```\nor\n\n```swift\nlet row = OKTableViewRow\u003cRowTableViewCell, RowModel\u003e(model: RowModel(type: .small))\nlet section = OKTableViewSection()\nliaison.append(section: section)\nliaison.append(row: row)\n```\n\n`OKTableViewRow` heights are similarly configured to `OKTableViewSection`:\n\n```swift\nrow.set(height: .height, 300)\n\nrow.set(height: .estimatedHeight, 210)\n\nrow.set(height: .height) { model -\u003e CGFloat in\n\tswitch model.type {\n\tcase .large:\n\t\treturn 400\n\tcase .medium:\n\t\treturn 200\n\tcase .small:\n\t\treturn 50\n\t}\n}\n```\n\nIn the event a height is not provided, the liaison will assume the cell is self sizing and return `UITableView.automaticDimension`.\n\nThe `OKTableViewRow` can be customized using `func set(command: OKTableViewRowCommand, with closure: @escaping (Cell, Model, IndexPath) -\u003e Void) ` at all the following lifecycle events:\n\n-  accessoryButtonTapped\n-  configuration\n-  delete\n-  didDeselect\n-  didEndDisplaying\n-  didEndEditing\n-  didHighlight\n-  didSelect\n-  didUnhighlight\n-  insert\n-  move\n-  reload\n-  willBeginEditing\n-  willDeselect\n-  willDisplay\n-  willSelect\n\n```swift\nrow.set(command: .configuration) { cell, model, indexPath in\n\tcell.label.text = model.text\n\tcell.label.font = .systemFont(ofSize: 13)\n\tcell.contentView.backgroundColor = .blue\n\tcell.selectionStyle = .none\n}\n\nrow.set(command: .didSelect) { cell, model, indexPath in\n\tprint(\"Cell: \\(cell) selected at IndexPath: \\(indexPath)\")\n}\n```\n\n`OKTableViewRow` can also utilize `UITableViewDataSourcePrefetching` by using `func set(prefetchCommand: OKTableViewPrefetchCommand, with closure: @escaping (Model, IndexPath) -\u003e Void)`\n\n```swift\nrow.set(prefetchCommand: .prefetch) { model, indexPath in\n\tmodel.downloadImage()\n}\n\nrow.set(prefetchCommand: .cancel) { model, indexPath in\n    model.cancelImageDownload()\n}\n```\n\n### Cell/View Registration\n`OKTableViewLiaison` handles cell \u0026 view registration for `UITableView` view reuse on your behalf utilizing your sections/rows `OKTableViewRegistrationType\u003cT\u003e`.\n\n`OKTableViewRegistrationType` tells the liaison whether your reusable view should be registered via a `Nib` or `Class`.\n\nBy default, `OKTableViewRow` is instantiated with `OKTableViewRegistrationType\u003cCell\u003e.defaultClassType`.\n\n`OKTableViewSection` supplementary view registration is encapsulated by its`OKTableViewSectionComponentDisplayOption`. By default, `OKTableViewSection` `componentDisplayOption` is instantiated with `.none`.\n\n### Pagination\n`OKTableViewLiaison` comes equipped to handle your pagination needs. To configure the liaison for pagination, simply set its `paginationDelegate` to an instance of `OKTableViewLiaisonPaginationDelegate`.\n\n`OKTableViewLiaisonPaginationDelegate` declares three methods:\n\n`func isPaginationEnabled() -\u003e Bool`, notifies the liaison if it should show the pagination spinner when the user scrolls past the last cell.\n\n`func paginationStarted(indexPath: IndexPath)`, passes through the indexPath of the last `OKTableViewRow` managed by the liaison.\n\n`func paginationEnded(indexPath: IndexPath)`, passes the indexPath of the first new `OKTableViewRow` appended by the liaison.\n\nTo update the liaisons results during pagination, simply use `append(sections: [OKAnyTableViewSection])` or `func append(rows: [OKAnyTableViewRow])` and the liaison will automatically handle the removal of the pagination spinner.\n\nTo use a custom pagination spinner, you can pass an instance `OKAnyTableViewRow` during the initialization of your `OKTableViewLiaison`. By default it uses `OKPaginationTableViewRow` provided by the framework.\n\n### Tips \u0026 Tricks\n\nBecause `OKTableViewSection` and `OKTableViewRow` utilize generic types and manage view/cell type registration, instantiating multiple different configurations of sections and rows can get verbose. Creating a subclass or utilizing a factory to create your various `OKTableViewRow`/`OKTableViewSectionComponent` types may be useful.\n\n```swift\nfinal class TextTableViewRow: OKTableViewRow\u003cPostTextTableViewCell, String\u003e {\n\tinit(text: String) {\n\t\tsuper.init(text,\n\t\tregistrationType: .defaultNibType)\n\t}\n}\n```\n\n```swift\nstatic func imageRow(with image: UIImage) -\u003e AnyTableViewRow {\n\tlet row = OKTableViewRow\u003cImageTableViewCell, UIImage\u003e(image)\n\n\trow.set(height: .height, 225)\n\n\trow.set(command: .configuration) { cell, image, indexPath in\n\t\tcell.contentImageView.image = image\n\t\tcell.contentImageView.contentMode = .scaleAspectFill\n\t}\n\n\treturn row\n}\n```\n\n## Contribution\n\n`OKTableViewLiaison` is a framework in its infancy. It's implementation is not perfect. Not all `UITableView` functionality has been `liaised` just yet. If you would like to help bring `OKTableViewLiaison` to a better place, feel free to make a pull request.\n\n## Authors\n\n✌️ Dylan Shine, dylan@okcupid.com\n\n## License\n\nOKTableViewLiaison is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokcupid%2FOKTableViewLiaison","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokcupid%2FOKTableViewLiaison","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokcupid%2FOKTableViewLiaison/lists"}