{"id":20449779,"url":"https://github.com/sandshellcreations/generic-tableview-datasource","last_synced_at":"2025-06-30T13:40:14.231Z","repository":{"id":143708800,"uuid":"197050019","full_name":"SandsHellCreations/Generic-TableView-DataSource","owner":"SandsHellCreations","description":"Generic TableView datasource that can be used to populate any type of listing with single cell listing, sectional listing and useful to populate different type of cells in one section using protocol based models and Generics.","archived":false,"fork":false,"pushed_at":"2020-07-26T11:34:42.000Z","size":32100,"stargazers_count":13,"open_issues_count":0,"forks_count":4,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-26T19:45:37.794Z","etag":null,"topics":["associated-type","editactionforrowat","generic-programming","generics","genericuitableviewdatasource","inheritance","kissmycode","leadingaction","protocol-oriented-programming","protocols","sandshellcreations","swift","swift5","swipe-gestures","swipe-to-delete","swipeable","trailingaction","tuples","uitableview","xcode"],"latest_commit_sha":null,"homepage":"https://sandshellcreations.github.io/Generic-TableView-DataSource/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SandsHellCreations.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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-07-15T18:16:13.000Z","updated_at":"2024-07-25T11:43:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"ff0c749d-5b16-49dd-968d-ca55cf8e3652","html_url":"https://github.com/SandsHellCreations/Generic-TableView-DataSource","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SandsHellCreations%2FGeneric-TableView-DataSource","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SandsHellCreations%2FGeneric-TableView-DataSource/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SandsHellCreations%2FGeneric-TableView-DataSource/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SandsHellCreations%2FGeneric-TableView-DataSource/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SandsHellCreations","download_url":"https://codeload.github.com/SandsHellCreations/Generic-TableView-DataSource/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654090,"owners_count":21140236,"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":["associated-type","editactionforrowat","generic-programming","generics","genericuitableviewdatasource","inheritance","kissmycode","leadingaction","protocol-oriented-programming","protocols","sandshellcreations","swift","swift5","swipe-gestures","swipe-to-delete","swipeable","trailingaction","tuples","uitableview","xcode"],"created_at":"2024-11-15T10:44:47.990Z","updated_at":"2025-04-13T02:10:39.639Z","avatar_url":"https://github.com/SandsHellCreations.png","language":"Swift","readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com//SandeepSpider811/Generic-TableView-DataSource/blob/master/GenericTableDataSource/Assets.xcassets/Poster.imageset/Poster.png?raw=true\" alt=\"Poster.png\" /\u003e\n\u003c/p\u003e\n\n## Features\n\n* Single data source can be used to design simple to complex every type of vertical listing using tableview.\n* Protocol oriented datasource with Generic models and associated types.\n* Native pull to refresh functionality handled in datasource with UIRefreshControl.\n* Infinite scrolling of tableview is also handled for paging.\n\n## Rules to follow if you've set your mind to use it.\n\n1. Every UITableView class should conform to **ReusableCell** protocol by inheriting it.\n2. Every UITableViewHeaderFooterView class should confirm to **ReusableHeaderFooterView** protocol by inheriting it.\n3. Your model class for setting data in UITableViewCell should confirm to **CellModelProvider** protocol by inherinting it.\n    #### CellModelProvider\n    ```\n    protocol CellModelProvider {\n    \n        typealias Property = (identifier: String, height: CGFloat, model: CellModelType?)\n    \n        associatedtype CellModelType\n    \n        var property: Property? { get set }\n        var leadingSwipeConfig: SKSwipeActionConfig? { get set }\n        var trailingSwipeConfig: SKSwipeActionConfig? { get set }\n    \n        init(_ _property: Property?, _ _leadingSwipe: SKSwipeActionConfig?, _ _trailingSwipe: SKSwipeActionConfig?)\n        \n    }\n    ```\n4. Your model class for setting data in UITableViewHeaderFooterView should confirm to **HeaderFooterModelProvider** protocol by inheriting it.\n    #### HeaderFooterModelProvider\n    ```\n    protocol HeaderFooterModelProvider {\n    \n        typealias HeaderProperty = (identifier: String?, height: CGFloat?, model: HeaderModelType?)\n        typealias FooterProperty = (identifier: String?, height: CGFloat?, model: FooterModelType?)\n    \n        associatedtype CellModelType : CellModelProvider\n        associatedtype HeaderModelType\n        associatedtype FooterModelType\n    \n        var headerProperty: HeaderProperty? { get set }\n        var footerProperty: FooterProperty? { get set }\n        var items: [CellModelType]? { get set }\n    \n        init(_ _header: HeaderProperty?, _ _footer: FooterProperty?, _ _items: [CellModelType]?)\n    \n    }\n    ```\n## Code Examples\n1. For single listing with single cell types.\n    Consider you have following model.\n    ```\n    class Example01Model {\n        var name: String?\n        var description: String?\n        var imageName: String?\n    \n        init(_ _name: String?, _ _desc: String?, _ _imageName: String?) {\n            name = _name\n            description = _desc\n            imageName = _imageName\n        }\n    }\n    ```\n    You can declare and instantiate tableViewDataSource instance like below.\n    ``` \n    private var items = [Example01Model]()\n    private var dataSource: TableDataSource\u003cDefaultHeaderFooterModel\u003cExample01Model\u003e, //Model Type for header footer conforming HeaderFooterModelProvider protocol\n                                              DefaultCellModel\u003cExample01Model\u003e, //Model Type for cell confirming CellModelProvider protocol\n                                              Example01Model\u003e? //Model Type of data to be used in cell\n    dataSource = TableDataSource\u003cDefaultHeaderFooterModel\u003cExample01Model\u003e, DefaultCellModel\u003cExample01Model\u003e, Example01Model\u003e.init(.SingleListing(items: items, identifier: Example01Cell.identfier, height: height), tableView)\n\n    ```\n    Setting data inside cell\n    ```\n    class Example01Cell: UITableViewCell, ReusableCell { //Inheriting Reuasable Cell Protocol\n    \n        typealias T = DefaultCellModel\u003cExample01Model\u003e //Declaring type of model to be used\n    \n        @IBOutlet weak var imgView: UIImageView!\n        @IBOutlet weak var lblTitle: UILabel!\n        @IBOutlet weak var lblDesc: UILabel!\n    \n    \n        var item: DefaultCellModel\u003cExample01Model\u003e? { // variable from which we can set data in cell\n            didSet {\n                imgView.layer.cornerRadius = 16.0\n                imgView.layer.borderColor = UIColor.darkGray.cgColor\n                imgView.layer.borderWidth = 0.8\n                imgView.image = UIImage(named: item?.property?.model?.imageName ?? \"\")\n                lblTitle.text = item?.property?.model?.name ?? \"\"\n                lblDesc.text = item?.property?.model?.description ?? \"\"\n            }\n        }\n    }\n    ```\n2. For multiple section and cell listing.\n    We need two models one for section footer and one for cell following rules that we've discussessed above.\n    ```\n    class SeasonHeaderFooterModel: HeaderFooterModelProvider { //conforming HeaderFooterModelProvider protocol\n    \n        typealias CellModelType = ActorCellModel //cell model type\n    \n        typealias HeaderModelType = Season //header model type\n    \n        typealias FooterModelType = Any //Footer model type\n    \n        var headerProperty: (identifier: String?, height: CGFloat?, model: Season?)?\n    \n        var footerProperty: (identifier: String?, height: CGFloat?, model: Any?)?\n    \n        var items: [ActorCellModel]?\n    \n        required init(_ _header: (identifier: String?, height: CGFloat?, model: Season?)?, _ _footer: (identifier: String?, height: CGFloat?, model: Any?)?, _ _items: [ActorCellModel]?) {\n            headerProperty = _header\n            footerProperty = _footer\n            items = _items\n        }\n    }\n    \n    class ActorCellModel: CellModelProvider { //confirming CellModelProvider protocol\n    \n        typealias CellModelType = Actor // model type of data to be used in cell\n    \n        var property: (identifier: String, height: CGFloat, model: Actor?)?\n    \n        required init(_ _property: (identifier: String, height: CGFloat, model: Actor?)?) {\n            property = _property\n        }\n    }\n    ```\n    You can declare and instantiate tableViewDataSource instance like below.\n    ```\n    private var items = [SeasonHeaderFooterModel]()\n    private var dataSource: TableDataSource\u003cSeasonHeaderFooterModel, ActorCellModel, Actor\u003e?\n    dataSource = TableDataSource\u003cSeasonHeaderFooterModel, ActorCellModel, Actor\u003e.init(.MultipleSection(items: items), tableView)\n    ```\n    Setting data inside header footer view\n    ```\n    class TVSeriesHeaderView: UITableViewHeaderFooterView, ReusableHeaderFooter {\n    \n        typealias T = SeasonHeaderFooterModel // model type of data to be used in header footer view \n    \n        @IBOutlet weak var lblTitle: UILabel!\n    \n        var item: SeasonHeaderFooterModel? {\n            didSet {\n                lblTitle.text = item?.headerProperty?.model?.title ?? \"\"\n            }\n        }\n    }\n    ```\n3. Table View Data source blocks can be used for further functionality.\n    ```\n    dataSource?.configureHeaderFooter = { (section, item, view) in\n        (view as? TVSeriesHeaderView)?.item = item\n    }\n    \n    dataSource?.configureCell = { (cell, item, indexPath) in\n        (cell as? Example01Cell)?.item = item\n    }\n    \n    dataSource?.addPullToRefresh = { [weak self] in\n        self?.pageNo = 0\n        self?.getNewDataWhenPulled()\n    }\n    \n    dataSource?.addInfiniteScrolling = { [weak self] in\n        self?.pageNo = (self?.pageNo ?? 0) + 1\n        self?.addMoreDataWithPaging()\n    }\n    \n    dataSource?.scrollDirection = { (direction) in\n        switch direction {\n        case .Up:\n            break\n        case .Down:\n            break\n        }\n    }\n    \n    dataSource?.didSelectRow = { (indexPath, item) in\n        \n    }\n    ```\n4. Leading and trailing swipe actions.\n    ```\n    protocol CellModelProvider {\n    \n    typealias Property = (identifier: String, height: CGFloat, model: CellModelType?)\n    \n    associatedtype CellModelType\n    \n    var property: Property? { get set }\n    var leadingSwipeConfig: SKSwipeActionConfig? { get set } // used to assign leading actions\n    var trailingSwipeConfig: SKSwipeActionConfig? { get set } // used to assign trailing actions\n    \n    init(_ _property: Property?, _ _leadingSwipe: SKSwipeActionConfig?, _ _trailingSwipe: SKSwipeActionConfig?)\n    \n    }\n    \n    // Internal class handling all actions in datasource\n    class SKSwipeActionConfig {\n    \n        private var actionValues: [(title: String?, image: UIImage?, backGroundColor: UIColor, identifier: String)]?\n        private var swipeActionConfig: UISwipeActionsConfiguration?\n        public var didSelectAction: ((_ identifer: String) -\u003e Void)?\n    \n        init(_ _actions: [(title: String?, image: UIImage?, backGroundColor: UIColor, identifier: String)]) {\n            actionValues = _actions\n            var skActions = [UIContextualAction]()\n    \n            actionValues?.forEach({ (item) in\n                let action = UIContextualAction(style: .normal, title: item.title, handler: { [weak self] (action, view, handler) in\n                    handler(true)\n                    self?.didSelectAction?(item.identifier)\n                })\n                action.backgroundColor = item.backGroundColor\n                action.image = item.image\n                skActions.append(action)\n            })\n    \n            swipeActionConfig = UISwipeActionsConfiguration(actions: skActions)\n            swipeActionConfig?.performsFirstActionWithFullSwipe = true\n        }\n    \n        func getConfig() -\u003e UISwipeActionsConfiguration? {\n            return swipeActionConfig\n        }\n    }\n    ```\n    block that can be used to handle leading and trailing actions.\n    ```\n    dataSource?.editActionForRow = { (indexPath, identifier, action) in\n        switch action {\n            case .Leading:\n                print(\"Leading action tapped\", \"Identifer: \\(identifier)\")\n                // do anything according to identifer if multiple actions\n            case .Trailing:\n                print(\"Trailing action tapped\", \"Identifer: \\(identifier)\")\n                // do anything according to identifer if multiple actions\n        }\n    }\n    ```\n\n    \n## Contact us for any queries and feature request\n[![Twitter][1.1]][1]\n[![Facebook][2.1]][2]\n[![Github][3.1]][3]\n[![Instagram][4.1]][4]\n[![Medium][5.1]][5]\n\n[1.1]: https://raw.githubusercontent.com/SandeepSpider811/Generic-TableView-DataSource/master/GenericTableDataSource/Assets.xcassets/social_twiiter.imageset/social_twiiter.png (twitter icon with padding)\n[2.1]: https://raw.githubusercontent.com/SandeepSpider811/Generic-TableView-DataSource/master/GenericTableDataSource/Assets.xcassets/social_facebook.imageset/social_facebook.png (facebook icon with padding)\n[3.1]: https://raw.githubusercontent.com/SandeepSpider811/Generic-TableView-DataSource/master/GenericTableDataSource/Assets.xcassets/social_github.imageset/social_github.png (github plus icon with padding)\n[4.1]: https://raw.githubusercontent.com/SandeepSpider811/Generic-TableView-DataSource/master/GenericTableDataSource/Assets.xcassets/social_instagram.imageset/social_instagram.png (Instagram icon with padding)\n[5.1]: https://raw.githubusercontent.com/SandeepSpider811/Generic-TableView-DataSource/master/GenericTableDataSource/Assets.xcassets/social_medium.imageset/social_medium.png (Medium icon with padding)\n\n[1]: https://twitter.com/SandsHell811\n[2]: https://www.facebook.com/Sandeep.kumar811\n[3]: https://github.com/SandeepSpider811\n[4]: https://www.instagram.com/sandshellcreations/\n[5]: https://medium.com/@sandshell811\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandshellcreations%2Fgeneric-tableview-datasource","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandshellcreations%2Fgeneric-tableview-datasource","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandshellcreations%2Fgeneric-tableview-datasource/lists"}