Swift μ-framework for efficient array diffs and datasource adapters.

Overview

Buffer Swift Platform License

Buffer

Swift μ-framework for efficient array diffs, collection observation and data source implementation.

C++11 port here

Installation

cd {PROJECT_ROOT_DIRECTORY}
curl "https://raw.githubusercontent.com/alexdrone/Buffer/master/bin/dist.zip" > dist.zip && unzip dist.zip && rm dist.zip;

Drag Buffer.framework in your project and add it as an embedded binary.

If you use xcodegen add the framework to your project.yml like so:

targets:
  YOUR_APP_TARGET:
    ...
    dependencies:
      - framework: PATH/TO/YOUR/DEPS/Buffer.framework

Installation with CocoaPods/Carthage (deprecated)

If you are using CocoaPods:

Add the following to your Podfile:

pod 'Buffer'

If you are using Carthage:

To install Carthage, run (using Homebrew):

$ brew update
$ brew install carthage

Then add the following line to your Cartfile:

github "alexdrone/Buffer" "master"    

Getting started

Buffer is designed to be very granular and has APIs with very different degrees of abstraction.

Managing a collection with Buffer

You can initialize and use Buffer in the following way.

import Buffer

class MyClass: BufferDelegate {

  lazy var buffer: Buffer<Foo> = {
    // The `sort` and the `filter` closure are optional - they are a convenient way to map the src array.
    let buffer = Buffer(initialArray: self.elements, sort: { $0.bar > $1.bar }, filter: { $0.isBaz })
    buffer.delegate = self
  }()

  var elements: [Foo] = [Foo]() {
    didSet {
      // When the elements are changed the buffer object will compute the difference and trigger
      // the invocation of the delegate methods.
      // The `synchronous` and `completion` arguments are optional.
      self.buffer.update(with: newValues, synchronous: false, completion: nil)
    }
  }


  //These methods will be called when the buffer has changedd.

  public func buffer(willChangeContent buffer: BufferType) {
    //e.g. self.tableView?.beginUpdates()

  }

  public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) {
    //e.g. Remove rows from a tableview
  }

  public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) {
  }

  public func buffer(didChangeContent buffer: BufferType) {
  }

  public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) {
  }

  public func buffer(didMoveElement buffer: BufferType, from: UInt, to: UInt) {
  }

  public func buffer(didChangeAllContent buffer: BufferType) {
  }
}

Built-in UITableView and UICollectionView adapter

One of the main use cases for Buffer is probably to apply changes to a TableView or a CollectionView. Buffer provides 2 adapter classes that implement the BufferDelegate protocol and automatically perform the required changes on the target tableview/collectionview when required.

import Buffer

class MyClass: UITableViewController {

  lazy var buffer: Buffer<Foo> = {
    // The `sort` and the `filter` closure are optional - they are convenient way to map the src array.
    let buffer = Buffer(initialArray: self.elements, sort: { $0.bar > $1.bar }, filter: { $0.isBaz })
    buffer.delegate = self
  }()

  var elements: [Foo] = [Foo]() {
    didSet {
      // When the elements are changed the buffer object will compute the difference and trigger
      // the invocation of the delegate methods.
      // The `synchronous` and `completion` arguments are optional.
      self.buffer.update(with: newValues, synchronous: false, completion: nil)
    }
  }

  let adapter: TableViewDiffAdapter<Foo>!

  init() {
    super.init()
    self.adapter = TableViewDiffAdapter(buffer: self.buffer, view: self.tableView)

    // Additionaly you can let the adapter be the datasource for your table view by passing a cell
    // configuration closure to the adpater.
    adapter.useAsDataSource { (tableView, object, indexPath) -> UITableViewCell in
      let cell = tableView.dequeueReusableCellWithIdentifier("MyCell")
	  			cell?.textLabel?.text = object.foo
	  			return cell
    }
  }

}

Component-Oriented TableView

Another convenient way to use Buffer is through the Buffer.TableView class. This abstraction allows for the tableView to reconfigure itself when its state (the elements) change.

import Buffer

class ViewController: UIViewController {

  lazy var tableView: TableView<FooModel> = {
    let tableView = TableView<FooModel>()
    return tableView
  }()

  lazy var elements: [ListItem<FooModel>] = {
    var elements = [ListItem<FooModel>]()
    for _ in 0...100 {
      // AnyListItem wraps the data and the configuration for every row in the tableview.
      let item = ListItem(type: UITableViewCell.self,
                          container: self.tableView,
                          model: FooModel(text: "Foo"))) {
        cell, model in
        cell.textLabel?.text = model.text
      }
      elements.append(item)
    }
    return elements
  }()

  override func viewDidLayoutSubviews() {
    self.tableView.frame = self.view.bounds
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addSubview(self.tableView)
    self.tableView.elements = self.elements
  }
}

Check the demo out to learn more about Buffer.

Credits

You might also like...
Swivl - A set of BLAS-accelerated linerar algebra structures and functions
Swivl - A set of BLAS-accelerated linerar algebra structures and functions

Swivl - Swift Vector Library A set of BLAS-accelerated linerar algebra structure

Commonly used data structures for Swift

Swift Collections is an open-source package of data structure implementations for the Swift programming language.

Fast sorted collections for Swift using in-memory B-trees
Fast sorted collections for Swift using in-memory B-trees

Fast Sorted Collections for Swift Using In-Memory B-Trees Overview Reference Documentation Optimizing Collections: The Book What Are B-Trees? Why In-M

Simple diff library in pure Swift

Diff Simple diffing library in pure Swift. Installing You can use Carthage or Swift Package Manager to install Diff. Usage Start by importing the pack

A functional tool-belt for Swift Language similar to Lo-Dash or Underscore.js in Javascript

Dollar Dollar is a Swift library that provides useful functional programming helper methods without extending any built in objects. It is similar to L

Swift type modelling the success/failure of arbitrary operations.

Result This is a Swift µframework providing ResultValue, Error. ResultValue, Error values are either successful (wrapping Value) or failed (wrappi

A Graph Data Structure in Pure Swift

SwiftGraph SwiftGraph is a pure Swift (no Cocoa) implementation of a graph data structure, appropriate for use on all platforms Swift supports (iOS, m

A Generic Priority Queue in Pure Swift

SwiftPriorityQueue SwiftPriorityQueue is a pure Swift (no Cocoa) implementation of a generic priority queue data structure, appropriate for use on all

Super lightweight DB written in Swift.
Super lightweight DB written in Swift.

Use of value types is recommended and we define standard values, simple structured data, application state and etc. as struct or enum. Pencil makes us

Comments
  • BufferDemo doesn't compile out of the box

    BufferDemo doesn't compile out of the box

    There is an absolute reference to the Buffer.framework containing alexusbergo.

    Perhaps change it to "relative to project" or to "relative to build products"

    opened by neoneye 1
  • Build Error: Multiple Command produce info.plist

    Build Error: Multiple Command produce info.plist

    Environment: Xcode 10, Swift 4.2 After deleting the info.plist from [build phase] -> [Copy Bundle Resources] , the problem is resolved. Below is the build error: Multiple commands produce '/Users/crewbuild/myagent/_work/6/output/iphoneos/Test-Release/build.sym/Test-Release-iphoneos/Buffer/Buffer.framework/Info.plist': 2018-10-17T18:19:48.9660210Z 1) Target 'Buffer' (project 'Pods') has copy command from '/Users/crewbuild/myagent/_work/6/s/Pods/Buffer/src/Info.plist' to '/Users/crewbuild/myagent/_work/6/output/iphoneos/Test-Release/build.sym/Test-Release-iphoneos/Buffer/Buffer.framework/Info.plist' 2018-10-17T18:19:48.9689440Z 2) Target 'Buffer' (project 'Pods') has process command with output '/Users/crewbuild/myagent/_work/6/output/iphoneos/Test-Release/build.sym/Test-Release-iphoneos/Buffer/Buffer.framework/Info.plist'

    opened by ychen820 0
  • Is Buffer a good solution for iOS Redux app ?

    Is Buffer a good solution for iOS Redux app ?

    HI, I'm looking into Redux flow for iOS recently, it does help me to normalize some questions, but I'm confusing with dealing big collection property in state, or multi properties in state

    for properties modified, I can detect and handle in didSet block, but I have no clue what's the best way to handle a big collection inserted/deleted/modified when new state is called, I want to do accuracy operation instead just call reloadData, especially I'm using AsyncDisplayKit, reload whole collectionView/tableView will cause some UI flash issue.

    Depends on a growing social app, properties might scale, Is Buffer the solution what I seeking ? How is the performance between Buffer with other diff frameworks ? ex: Dwifft

    Also Do you think ReSwift + Buffer + AsyncDisplayKit make sense ? I'm kind tired of MVC, lol

    opened by PatrickSCLin 0
  • mainThread VS mainQueue

    mainThread VS mainQueue

    There are quite a few checks like NSThread.isMainThread() in the code. Maybe this should be changed to checking for the main queue instead?

    Here's sample code to check for the queue instead, based on http://blog.benjamin-encz.de/post/main-queue-vs-main-thread/, where the difference is explained, too:

    private let mainQueueKey = UnsafeMutablePointer<Void>.alloc(1)
    private let mainQueueValue = UnsafeMutablePointer<Void>.alloc(1)
    
    // Associate a key-value pair with the main queue
    dispatch_queue_set_specific(
        dispatch_get_main_queue(), 
        mainQueueKey, 
        mainQueueValue, 
        nil
    )
    
    func dispatch_ensure_main_queue(block: dispatch_block_t) {
    
        // Check for presence of key-value pair on current queue
        if (dispatch_get_specific(mainQueueKey) == mainQueueValue) {
            // if we found right value for key, execute immediately
            print("main queue")
            block()
        } else {
            // otherwise dispatch on main queue now
            // /!\ Use dispatch_sync cautiously
            // it can cause deadlocks!
            dispatch_sync(dispatch_get_main_queue()) {
                print("not main queue")
                block()
            }
        }
    
        return image
    }
    
    opened by DivineDominion 5
Releases(2.1)
Owner
Alex Usbergo
Technical Lead | Sr Software Engineer at Google. Ex-Microsoft/Ex-Skype.
Alex Usbergo
Differific - a fast and convenient diffing framework.

Differific Description Differific is a diffing tool that helps you compare Hashable objects using the Paul Heckel's diffing algorithm. Creating a chan

Christoffer Winterkvist 127 Jun 3, 2022
TemplateKit - React inspired framework for building component-based user interfaces in Swift

TemplateKit React-inspired framework for building component-based user interface

null 0 Feb 6, 2022
Swift-extensions - Swift package extending the Swift programming language.

swift-extensions A package containing extensions for the Swift programming language. Contribution Reporting a bug If you find a bug, please open a bug

Alexandre H. Saad 2 Jun 12, 2022
Examples of commonly used data structures and algorithms in Swift.

Swift Structures This project provides a framework for commonly used data structures and algorithms written in a new iOS development language called S

Wayne Bishop 2.1k Dec 28, 2022
Algorithms and data structures in Swift, with explanations!

Welcome to the Swift Algorithm Club! Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Sw

raywenderlich 27.3k Jan 8, 2023
Swift library to generate differences and patches between collections.

Differ Differ generates the differences between Collection instances (this includes Strings!). It uses a fast algorithm (O((N+M)*D)) to do this. Featu

Tony Arnold 628 Dec 29, 2022
A Swift probability and statistics library

Probably Probably is a set of Swift structures for computing the probability and cumulative distributions of different probablistic functions. Right n

Harlan Haskins 270 Dec 2, 2022
:droplet: A generic view model for both basic and complex scenarios

Brick Description Brick is a generic view model for both basic and complex scenarios. Mapping a basic table view cells is as easy as pie, if you have

HyperRedink 59 Jul 31, 2021
KeyPathKit is a library that provides the standard functions to manipulate data along with a call-syntax that relies on typed keypaths to make the call sites as short and clean as possible.

KeyPathKit Context Swift 4 has introduced a new type called KeyPath, with allows to access the properties of an object with a very nice syntax. For in

Vincent Pradeilles 406 Dec 25, 2022
Extension of Diffable API which allow not duplicate code and use less models. Included example for SideBar.

SPDiffable Apple's diffable API requerid models for each object type. If you want use it in many place, you pass many time to implemenet and get over

Ivan Vorobei 114 Jan 3, 2023