{"id":2885,"url":"https://github.com/bannzai/conv","last_synced_at":"2025-04-11T08:42:54.153Z","repository":{"id":54620756,"uuid":"131003248","full_name":"bannzai/Conv","owner":"bannzai","description":"Conv smart represent UICollectionView data structure more than UIKit.","archived":false,"fork":false,"pushed_at":"2021-02-07T23:51:58.000Z","size":1964,"stargazers_count":159,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-06T05:00:01.140Z","etag":null,"topics":["ios","swift","uicollectionview"],"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/bannzai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-25T12:30:47.000Z","updated_at":"2025-03-23T03:37:18.000Z","dependencies_parsed_at":"2022-08-13T21:50:19.972Z","dependency_job_id":null,"html_url":"https://github.com/bannzai/Conv","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannzai%2FConv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannzai%2FConv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannzai%2FConv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannzai%2FConv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bannzai","download_url":"https://codeload.github.com/bannzai/Conv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248362514,"owners_count":21091144,"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":["ios","swift","uicollectionview"],"created_at":"2024-01-05T20:16:25.425Z","updated_at":"2025-04-11T08:42:54.125Z","avatar_url":"https://github.com/bannzai.png","language":"Swift","funding_links":[],"categories":["UI"],"sub_categories":["Table View / Collection View"],"readme":"\u003cdiv align=\"center\" \u003e\n  \u003cimg width=\"70%\" src=\"Logo/conv_logo.png\" /\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg alt=\"Swift4\" src=\"https://img.shields.io/badge/language-swift4-blue.svg?style=flat\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://cocoapods.org/pods/Conv\"\u003e\u003cimg alt=\"CocoaPods\" src=\"https://img.shields.io/cocoapods/v/Conv.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-brightgreen.svg?style=flat\"/\u003e\u003c/a\u003e\n  \u003c/br\u003e\n  \u003ca href=\"https://developer.apple.com/swift/\"\u003e\u003cimg alt=\"Platform\" src=\"https://img.shields.io/badge/platform-iOS-green.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/bannzai/Conv/blob/master/LICENSE.txt\"\u003e\u003cimg alt=\"Lincense\" src=\"http://img.shields.io/badge/license-MIT-000000.svg?style=flat\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\n# Conv\n\nConv smart represent UICollectionView data structure more than UIKit.  \nEasy definition for UICollectionView DataSource and Delegate methods.  \n\n\u003cimg width=\"100%\" src=\"https://user-images.githubusercontent.com/10897361/45803758-54c4e780-bcf5-11e8-8724-7ea779589331.png\" /\u003e\n\n\nAnd Conv reload fast to use diffing algorithm based on the Paul Heckel's algorithm.   \n\n|  Insert and Delete  |  Move item and section  |\n| ---- | ---- |\n|  \u003cimg width=\"320px\" src=\"https://user-images.githubusercontent.com/10897361/44513426-484e6e80-a6f8-11e8-83cc-78e533521588.gif\" /\u003e  |  \u003cimg width=\"320px\" src=\"https://user-images.githubusercontent.com/10897361/44513427-48e70500-a6f8-11e8-9e1e-7957f60a2918.gif\" /\u003e  |\n\nConv(called KONBU) means Seaweed in Japan.  \nThis library is inspired by [Shoyu](https://github.com/yukiasai/shoyu). Thanks [@yukiasai](https://github.com/yukiasai).\n\n# Usage\n**First**, Conv need to prepare array of definition datastructure for section and item.\nAnd then it should conform `Differenciable` protocol for difference algorithm.\n\n### Section\n```swift\nenum SectionType: Int {\n  case one\n  case two\n  case three\n\n  static var allCases: [SectionType] {\n    return [.one, .two, .three]\n  }\n}\n\nextension SectionType: Differenciable {\n  var differenceIdentifier: DifferenceIdentifier {\n    return \"\\(self)\"\n  }\n}\n```\n\n```swift\nlet sectionTypes = SectionType.allCases\n```\n\n### Item\n```swift\nstruct ItemModel {\n    let index: Int\n    let imageName: String\n    var image: UIImage {\n        return UIImage(named: imageName)!\n    }\n}\n\nextension ItemModel: Differenciable {\n    var differenceIdentifier: DifferenceIdentifier {\n        return \"\\(index)\" + imageName\n    }\n}\n```\n\n```swift\nlet itemModels = [\n    ItemModel(index: 1, imageName: \"forest\"),\n    ItemModel(index: 2, imageName: \"moon\"),\n    ItemModel(index: 3, imageName: \"pond\"),\n    ItemModel(index: 4, imageName: \"river\"),\n]\n```\n\n**Second**, start to define data structure for section and item.   \nIt use prepared Differenciable array.  \n\n```swift\ncollectionView\n    .conv // #1\n    .diffing() \n    .start() \n    .append(for: sectionTypes) { (sectionType, section) in // #2\n        section.append(.header, headerOrFooter: { (header: SectionHeaderFooter\u003cListCollectionReusableView\u003e) in // #3\n            header.reusableIdentifier = \"ListCollectionReusableView\"\n            header.size = CGSize(width: UIScreen.main.bounds.width, height: 50)\n            header.configureView { view, _ in\n                view.nameLabel.text = \"\\(sectionType)\".uppercased()\n                view.nameLabel.textColor = .white\n                view.backgroundColor = sectionType.backgroundColor\n            }\n        })\n        section.append(for: itemModels, items: { (itemModel, item: Item\u003cListCollectionViewCell\u003e) in // #4\n            item.reusableIdentifier = \"ListCollectionViewCell\"\n            item.sizeFor({ _ -\u003e CGSize in\n                let gridCount: CGFloat = 3\n                let edge = floor((UIScreen.main.bounds.width - (gridCount - 1)) / gridCount)\n                let size = CGSize(width: edge, height: edge)\n                return size\n            })\n            \n            item.configureCell { (cell, info) in\n                cell.setup(with: itemModel)\n            }\n            \n            item.didSelect { [weak self] (item) in\n                let viewController = DetailViewController(imageName: itemModel.imageName)\n                self?.navigationController?.pushViewController(viewController, animated: true)\n            }\n        })\n}\n```\n\nThis swift code has the following meaning. It explain for `#` mark in code.\n1. Start to define UICollectionView data structure it using `Conv`.\n2. Append sections that number of sectionTypes. And start define about section. \n3. Append section header for each section. And start define about section header.\n4. Append items that number of itemModels for each section. And start define about item.\n\n**Last**, If you want to render of `collectionView`, you call `collectionView.update()` your best timing.  \n`update()` calculate diff for minimum reloading data between before section and between before items.\n\n```swift\ncollectionView.conv.update()\n```\n\nOr if you want to all realod cells, you can call `reload()`. \nIt will be same behavior of `collectionView.reloadData()`.\n\n```swift\ncollectionView.conv.reload()\n```\n\nYou can see more example to [ConvExmaple](https://github.com/bannzai/Conv/tree/master/ConvExample/)  \n\n# Algorithm\nConv to use diffing algorithm based on the Paul Heckel's algorithm.    \nAnd I also referred to other libraries below.  \n\n- https://github.com/mcudich/HeckelDiff\n- https://github.com/ra1028/DifferenceKit\n- https://github.com/Instagram/IGListKit/\n\n# Install\n## CocoaPods\nConv is available through Cocoapods.  \nYou can write it into target and exec `pod install`.\n\n```\npod 'Conv'\n```\n\n## Carthage\nConv is available through Carhtage.  \nYou can write it into target and exec `carthage update --platform iOS`.\nAnd find conv framework and embed your project.\n\n```\ngithub 'bannzai/Conv'\n```\n\n# Why Conv?\nUIKit.UICollectionView has some problems.\n\n1. UICollectionView.dequeueXXX method not type safe. So, should convert to want class each cells. \n2. UICollectionViewDataSource and UICollectionViewDelegate(or DelegateFlowLayout) far away each configured functions. So, reading configuration flow for each indexPath very difficalt.\n3. Many case to use UICollectionView with Array. But extract element from array using indexPath many time.\n\nConv resolve these problem.\n1. Conv does not need to call UICollectionView.dequeueXXX. Because you can define configureCell method and get converted custom class cell. \n\n```swift\nsection.append(for: itemModels, items: { (itemModel, item: Item\u003cListCollectionViewCell\u003e) in // #4\n    ...\n    item.configureCell { (cell, info) in\n        // cell is converted ListCollectionViewCell\n        cell.setup(with: itemModel)\n    }\n})\n```\n\n2. You can write to neary for each UICollectionView component. section,item,header and footer.\nSo, this definition to be natural expression for UICollectionView data strcture, hierarchy, releation.\n\n3. When append section or item, you can passed allCases for configure UICollectionView.\nNext each element pass closure argument that define Conv.Section or Conv.Item.\nSo, You can represent CollectionView data structure with extracted each element.\n\n# LICENSE\n[Conv](https://github.com/bannzai/Conv/) is released under the MIT license. See [LICENSE](https://github.com/bannzai/Conv/blob/master/LICENSE.txt) for details.\n\nHeader logo is released [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/deed) license. Original design by [noainoue](https://github.com/noainoue).\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbannzai%2Fconv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbannzai%2Fconv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbannzai%2Fconv/lists"}