Skip to content

Instantly share code, notes, and snippets.

@osteslag
Created February 7, 2016 09:53
Show Gist options
  • Save osteslag/b7b22aa29e1c1dd5a4a6 to your computer and use it in GitHub Desktop.
Save osteslag/b7b22aa29e1c1dd5a4a6 to your computer and use it in GitHub Desktop.
Untested Changeset extension on UITableView and UICollectionView
//
// UIKit+Changeset.swift
// Copyright (c) 2016 Joachim Bondo. All rights reserved.
//
import UIKit
import Changeset
public extension UITableView {
/// Performs batch updates on the table view, given the edits of a Changeset, and animates the transition.
public func updateWithEdits<T: Equatable> (edits: [Edit<T>], inSection section: Int) {
guard !edits.isEmpty else { return }
let indexPaths = batchIndexPathsFromEdits(edits, inSection: section)
self.beginUpdates()
if !indexPaths.deletions.isEmpty { self.deleteRowsAtIndexPaths(indexPaths.deletions, withRowAnimation: .Automatic) }
if !indexPaths.insertions.isEmpty { self.insertRowsAtIndexPaths(indexPaths.insertions, withRowAnimation: .Automatic) }
if !indexPaths.updates.isEmpty { self.reloadRowsAtIndexPaths(indexPaths.updates, withRowAnimation: .Automatic) }
indexPaths.moves.forEach { self.moveRowAtIndexPath($0.from, toIndexPath: $0.to) }
self.endUpdates()
}
}
public extension UICollectionView {
/// Performs batch updates on the table view, given the edits of a Changeset, and animates the transition.
public func updateWithEdits<T: Equatable> (edits: [Edit<T>], inSection section: Int, completion: ((Bool) -> Void)?) {
guard !edits.isEmpty else { return }
let indexPaths = batchIndexPathsFromEdits(edits, inSection: section)
self.performBatchUpdates({
if !indexPaths.deletions.isEmpty { self.deleteItemsAtIndexPaths(indexPaths.deletions) }
if !indexPaths.insertions.isEmpty { self.insertItemsAtIndexPaths(indexPaths.insertions) }
if !indexPaths.updates.isEmpty { self.reloadItemsAtIndexPaths(indexPaths.updates) }
indexPaths.moves.forEach { self.moveItemAtIndexPath($0.from, toIndexPath: $0.to) }
}, completion: completion)
}
}
internal func batchIndexPathsFromEdits<T: Equatable> (edits: [Edit<T>], inSection section: Int) -> (insertions: [NSIndexPath], deletions: [NSIndexPath], moves: [(from: NSIndexPath, to: NSIndexPath)], updates: [NSIndexPath]) {
var insertions = [NSIndexPath]()
var deletions = [NSIndexPath]()
var moves = [(from: NSIndexPath, to: NSIndexPath)]()
var updates = [NSIndexPath]()
for edit in edits {
let destinationIndexPath = NSIndexPath(forRow: edit.destination, inSection: section)
switch edit.operation {
case .Deletion:
deletions.append(destinationIndexPath)
case .Insertion:
insertions.append(destinationIndexPath)
case .Move(let origin):
let originIndexPath = NSIndexPath(forRow: origin, inSection: section)
moves.append(from: originIndexPath, to: destinationIndexPath)
case .Substitution:
updates.append(destinationIndexPath)
}
}
return (insertions: insertions, deletions: deletions, moves: moves, updates: updates)
}
@osteslag
Copy link
Author

osteslag commented Feb 7, 2016

See the discussion on Changeset #12.

@andreyz
Copy link

andreyz commented Feb 7, 2016

I've written something similar myself. Great work @osteslag.

@andreyz
Copy link

andreyz commented Feb 7, 2016

maybe here we should use [weak self]?

@osteslag
Copy link
Author

osteslag commented Feb 7, 2016

Thanks, @andreyz :-)

Why would you want weak self? In case the view would go away during the updates? Is that a risk we need to manage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment