{"id":1035,"url":"https://github.com/mcudich/HeckelDiff","last_synced_at":"2025-07-30T20:30:48.568Z","repository":{"id":56914444,"uuid":"74520285","full_name":"mcudich/HeckelDiff","owner":"mcudich","description":"A fast Swift diffing library.","archived":false,"fork":false,"pushed_at":"2020-07-19T22:46:58.000Z","size":60,"stargazers_count":166,"open_issues_count":5,"forks_count":28,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-09T20:52:54.395Z","etag":null,"topics":["batched-updates","diffing","swift","uicollectionviews"],"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/mcudich.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":"2016-11-22T22:50:21.000Z","updated_at":"2025-07-06T11:53:32.000Z","dependencies_parsed_at":"2022-08-21T03:50:28.759Z","dependency_job_id":null,"html_url":"https://github.com/mcudich/HeckelDiff","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/mcudich/HeckelDiff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FHeckelDiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FHeckelDiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FHeckelDiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FHeckelDiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcudich","download_url":"https://codeload.github.com/mcudich/HeckelDiff/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FHeckelDiff/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267935142,"owners_count":24168269,"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","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["batched-updates","diffing","swift","uicollectionviews"],"created_at":"2024-01-05T20:15:37.541Z","updated_at":"2025-07-30T20:30:48.277Z","avatar_url":"https://github.com/mcudich.png","language":"Swift","funding_links":[],"categories":["Data Structures / Algorithms","Swift"],"sub_categories":["Getting Started","Other free courses","Linter"],"readme":"# HeckelDiff\n[![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](#)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/HeckelDiff.svg)](https://img.shields.io/cocoapods/v/HeckelDiff)\n[![Platform](https://img.shields.io/cocoapods/p/HeckelDiff.svg?style=flat)](http://cocoadocs.org/docsets/HeckelDiff)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)\n\nPure Swift implementation of Paul Heckel's *A Technique for Isolating Differences Between Files*\n\n## Features\n\nThis is a simple diff algorithm that provides the minimum set of steps to transform one collection into another. Transformations are listed as discrete operations:\n* **Insertion** - what items should be inserted into the array, and at what index.\n* **Deletion** - what items should be removed from the array, and at what index.\n* **Move** - what items should be moved, and their origin and destination indices.\n* **Update** - what items should be updated/replaced with new context, and at what index.\n\nThese operations are calculated in **linear** time, using the algorithm described in [this paper](http://dl.acm.org/citation.cfm?id=359467).\n\nKnowing this set of operations is especially handy for efficiently updating **UITableViews** and **UICollectionViews**.\n\n## Example\n\nConsider a simple example that compares lists of integers:\n```swift\nlet o = [1, 2, 3, 3, 4]\nlet n = [2, 3, 1, 3, 4]\nlet result = diff(o, n)\n// [.move(1, 0), .move(2, 1), .move(0, 2)]\n\nlet o = [0, 1, 2, 3, 4, 5, 6, 7, 8]\nlet n = [0, 2, 3, 4, 7, 6, 9, 5, 10]\nlet result = diff(o, n)\n// [.delete(1), .delete(8), .move(7, 4), .insert(6), .move(5, 7), .insert(8)]\n```\n\n`orderedDiff` is also available, which provides a set of operations that are friendly for batched updates in UIKit contexts (note how `move` is replaced by pairs of `insert` and `delete` operations):\n```swift\nlet o = [1, 2, 3, 3, 4]\nlet n = [2, 3, 1, 3, 4]\nlet result = orderedDiff(o, n)\n// [.delete(2), .delete(1), .delete(0), .insert(0), .insert(1), .insert(2)]\n```\n\n## UITableView/UICollectionView Support\n\nHeckelDiff has built-in support for generating efficient batched updates for `UITableView` and `UICollectionView`. Methods are made available on both that allow informing the corresponding table or collection view that their data model has changed.\n\nFor example:\n```swift\ntableView.applyDiff(previousItems, newItems, withAnimation: .fade)\n```\nor\n```swift\ncollectionView.applyDiff(previousItems, newItems)\n```\n\n## Update Support\n\nElements in collections passed into `diff` must conform to `Hashable`. HeckelDiff uses elements' `hashValues` to determine whether they should be **inserted**, **deleted** or **moved**. In some cases, elements are instead marked for **update**. This is because even though the `hashValues` of two elements might be equivalent, the elements may not be **equal**. You can take advantage of this by implementing the `Hashable` protocol in such a way that your elements get updated when appropriate.\n\nFor example, you may have two records that refer to the same person (perhaps you use a record ID as a hash value). You may want to support a case where a person's phone number may change, but the record itself remains in the same position in the array. Your `Equatable` implementation may take the phone number value into account, whereas your `hashValue` may only reflect the underlying record ID value.\n\nIn the context of a `UITableView` or `UICollectionView`, you would most efficiently handle this by reloading the given row that needs updating (rather than deleting it and re-inserting it). Use the supplied `applyDiff` functions to have HeckelDiff perform this for you.\n\n## Installation\n\n#### Carthage\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nAdd the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile):\n\n```ogdl\ngithub \"mcudich/HeckelDiff\"\n```\n\nRun `carthage update`, then make sure to add `HeckelDiff.framework` to \"Linked Frameworks and Libraries\" and \"copy-frameworks\" Build Phases.\n\n#### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate TemplateKit into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '10.0'\nuse_frameworks!\n\ntarget '\u003cYour Target Name\u003e' do\n    pod 'HeckelDiff', '~\u003e 0.1.0'\nend\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n## Requirements\n\n- iOS 9.0+\n- Xcode 8.0+\n- Swift 3.0+\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcudich%2FHeckelDiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcudich%2FHeckelDiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcudich%2FHeckelDiff/lists"}