{"id":15037737,"url":"https://github.com/alexdrone/buffer","last_synced_at":"2025-10-24T18:05:38.166Z","repository":{"id":56904019,"uuid":"59575358","full_name":"alexdrone/Buffer","owner":"alexdrone","description":"Swift μ-framework for efficient array diffs and datasource adapters.","archived":false,"fork":false,"pushed_at":"2019-10-07T19:27:04.000Z","size":11022,"stargazers_count":351,"open_issues_count":4,"forks_count":13,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-08T03:08:48.658Z","etag":null,"topics":["buffer","datasource","diffing","edit-distance","iglistkit","ios","keypath","kvo","levenshtein-distance","swift","swift-3","tableview"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexdrone.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-05-24T13:26:37.000Z","updated_at":"2025-03-23T10:48:52.000Z","dependencies_parsed_at":"2022-08-21T02:50:14.618Z","dependency_job_id":null,"html_url":"https://github.com/alexdrone/Buffer","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FBuffer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FBuffer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FBuffer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdrone%2FBuffer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexdrone","download_url":"https://codeload.github.com/alexdrone/Buffer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247767234,"owners_count":20992547,"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":["buffer","datasource","diffing","edit-distance","iglistkit","ios","keypath","kvo","levenshtein-distance","swift","swift-3","tableview"],"created_at":"2024-09-24T20:35:29.528Z","updated_at":"2025-10-24T18:05:38.073Z","avatar_url":"https://github.com/alexdrone.png","language":"Swift","readme":"\n# Buffer [![Swift](https://img.shields.io/badge/swift-5-orange.svg?style=flat)](#) [![Platform](https://img.shields.io/badge/platform-iOS|macOS-lightgrey.svg?style=flat)](#) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)\n\n\u003cimg src=\"https://raw.githubusercontent.com/alexdrone/Buffer/master/docs/logo_small.png\" width=150 alt=\"Buffer\" align=right /\u003e\n\nSwift μ-framework for efficient array diffs, collection observation and data source implementation.\n\n[C++11 port here](https://github.com/alexdrone/libbuffer)\n\n### Installation\n\n```bash\ncd {PROJECT_ROOT_DIRECTORY}\ncurl \"https://raw.githubusercontent.com/alexdrone/Buffer/master/bin/dist.zip\" \u003e dist.zip \u0026\u0026 unzip dist.zip \u0026\u0026 rm dist.zip;\n```\n\nDrag `Buffer.framework` in your project and add it as an embedded binary.\n\nIf you use [xcodegen](https://github.com/yonaskolb/XcodeGen) add the framework to your *project.yml* like so:\n\n```yaml\ntargets:\n  YOUR_APP_TARGET:\n    ...\n    dependencies:\n      - framework: PATH/TO/YOUR/DEPS/Buffer.framework\n```\n\n## Installation with CocoaPods/Carthage (deprecated)\n\nIf you are using **CocoaPods**:\n\n\nAdd the following to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html):\n\n```ruby\npod 'Buffer'\n```\n\nIf you are using **Carthage**:\n\n\nTo install Carthage, run (using Homebrew):\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\n\nThen add the following line to your `Cartfile`:\n\n```\ngithub \"alexdrone/Buffer\" \"master\"    \n```\n\n\n# Getting started\n\nBuffer is designed to be very granular and has APIs with very different degrees of abstraction.\n\n\n### Managing a collection with Buffer\n\nYou can initialize and use **Buffer** in the following way.\n\n```swift\n\nimport Buffer\n\nclass MyClass: BufferDelegate {\n\n  lazy var buffer: Buffer\u003cFoo\u003e = {\n    // The `sort` and the `filter` closure are optional - they are a convenient way to map the src array.\n    let buffer = Buffer(initialArray: self.elements, sort: { $0.bar \u003e $1.bar }, filter: { $0.isBaz })\n    buffer.delegate = self\n  }()\n\n  var elements: [Foo] = [Foo]() {\n    didSet {\n      // When the elements are changed the buffer object will compute the difference and trigger\n      // the invocation of the delegate methods.\n      // The `synchronous` and `completion` arguments are optional.\n      self.buffer.update(with: newValues, synchronous: false, completion: nil)\n    }\n  }\n\n\n  //These methods will be called when the buffer has changedd.\n\n  public func buffer(willChangeContent buffer: BufferType) {\n    //e.g. self.tableView?.beginUpdates()\n\n  }\n\n  public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) {\n    //e.g. Remove rows from a tableview\n  }\n\n  public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) {\n  }\n\n  public func buffer(didChangeContent buffer: BufferType) {\n  }\n\n  public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) {\n  }\n\n  public func buffer(didMoveElement buffer: BufferType, from: UInt, to: UInt) {\n  }\n\n  public func buffer(didChangeAllContent buffer: BufferType) {\n  }\n}\n\n```\n\n### Built-in UITableView and UICollectionView adapter\n\nOne of the main use cases for **Buffer** is probably to apply changes to a TableView or a CollectionView.\n**Buffer** provides 2 adapter classes that implement the `BufferDelegate` protocol and automatically perform the required\nchanges on the target tableview/collectionview when required.\n\n```swift\n\nimport Buffer\n\nclass MyClass: UITableViewController {\n\n  lazy var buffer: Buffer\u003cFoo\u003e = {\n    // The `sort` and the `filter` closure are optional - they are convenient way to map the src array.\n    let buffer = Buffer(initialArray: self.elements, sort: { $0.bar \u003e $1.bar }, filter: { $0.isBaz })\n    buffer.delegate = self\n  }()\n\n  var elements: [Foo] = [Foo]() {\n    didSet {\n      // When the elements are changed the buffer object will compute the difference and trigger\n      // the invocation of the delegate methods.\n      // The `synchronous` and `completion` arguments are optional.\n      self.buffer.update(with: newValues, synchronous: false, completion: nil)\n    }\n  }\n\n  let adapter: TableViewDiffAdapter\u003cFoo\u003e!\n\n  init() {\n    super.init()\n    self.adapter = TableViewDiffAdapter(buffer: self.buffer, view: self.tableView)\n\n    // Additionaly you can let the adapter be the datasource for your table view by passing a cell\n    // configuration closure to the adpater.\n    adapter.useAsDataSource { (tableView, object, indexPath) -\u003e UITableViewCell in\n      let cell = tableView.dequeueReusableCellWithIdentifier(\"MyCell\")\n\t  \t\t\tcell?.textLabel?.text = object.foo\n\t  \t\t\treturn cell\n    }\n  }\n\n}\n\n\n```\n\n### Component-Oriented TableView\n\nAnother convenient way to use **Buffer** is through the `Buffer.TableView` class.\nThis abstraction allows for the tableView to reconfigure itself when its state (the elements) change.\n\n```swift\n\nimport Buffer\n\nclass ViewController: UIViewController {\n\n  lazy var tableView: TableView\u003cFooModel\u003e = {\n    let tableView = TableView\u003cFooModel\u003e()\n    return tableView\n  }()\n\n  lazy var elements: [ListItem\u003cFooModel\u003e] = {\n    var elements = [ListItem\u003cFooModel\u003e]()\n    for _ in 0...100 {\n      // AnyListItem wraps the data and the configuration for every row in the tableview.\n      let item = ListItem(type: UITableViewCell.self,\n                          container: self.tableView,\n                          model: FooModel(text: \"Foo\"))) {\n        cell, model in\n        cell.textLabel?.text = model.text\n      }\n      elements.append(item)\n    }\n    return elements\n  }()\n\n  override func viewDidLayoutSubviews() {\n    self.tableView.frame = self.view.bounds\n  }\n\n  override func viewDidLoad() {\n    super.viewDidLoad()\n    self.view.addSubview(self.tableView)\n    self.tableView.elements = self.elements\n  }\n}\n\n\n```\n\nCheck the demo out to learn more about Buffer.\n\n### Credits\n\n- Diff algorithm from IGListKit/IGListDiff\n\t* [IGListKit original ObjC++ implementation](https://github.com/Instagram/IGListKit)\n\t* [ListDiff Swift port](https://github.com/lxcid/ListDiff)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdrone%2Fbuffer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexdrone%2Fbuffer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdrone%2Fbuffer/lists"}