Skip to content

Commit

Permalink
Merge pull request #29 from osteslag/uikit-extensions
Browse files Browse the repository at this point in the history
Embed UIKit Extensions
  • Loading branch information
Joachim Bondo authored Nov 23, 2016
2 parents d49bfd2 + c154031 commit 24d2bd8
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 20 deletions.
6 changes: 3 additions & 3 deletions Changeset.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
29078AC81C895E9F00FBBEC9 /* DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29078AC71C895E9F00FBBEC9 /* DataSource.swift */; };
29214F661DE4DF9D000677A7 /* UIKit+Changeset.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC41787B1C6EF39100296FD8 /* UIKit+Changeset.swift */; };
29828DD41C2A899E0056284E /* Changeset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29828DC91C2A899D0056284E /* Changeset.framework */; };
29828DD91C2A899E0056284E /* ChangesetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29828DD81C2A899E0056284E /* ChangesetTests.swift */; };
29828DE41C2A8BD40056284E /* Changeset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29828DE31C2A8BD40056284E /* Changeset.swift */; };
Expand All @@ -17,7 +18,6 @@
CC41786F1C6EE5E000296FD8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC41786E1C6EE5E000296FD8 /* Assets.xcassets */; };
CC4178721C6EE5E000296FD8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CC4178701C6EE5E000296FD8 /* LaunchScreen.storyboard */; };
CC41787A1C6EE8C700296FD8 /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4178791C6EE8C700296FD8 /* CollectionViewCell.swift */; };
CC41787C1C6EF39100296FD8 /* UIKit+Changeset.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC41787B1C6EF39100296FD8 /* UIKit+Changeset.swift */; };
CC41787E1C6EF41000296FD8 /* Changeset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29828DC91C2A899D0056284E /* Changeset.framework */; };
CC41787F1C6EF41000296FD8 /* Changeset.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 29828DC91C2A899D0056284E /* Changeset.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CC4178841C6EF88B00296FD8 /* Changeset+Naive.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4178831C6EF88B00296FD8 /* Changeset+Naive.swift */; };
Expand Down Expand Up @@ -134,6 +134,7 @@
isa = PBXGroup;
children = (
29828DE31C2A8BD40056284E /* Changeset.swift */,
CC41787B1C6EF39100296FD8 /* UIKit+Changeset.swift */,
29828DCE1C2A899D0056284E /* Info.plist */,
);
path = Sources;
Expand Down Expand Up @@ -175,7 +176,6 @@
CC3454A91C854BEF00CE0C4D /* TableViewController.swift */,
CCDD53611C7D901F00FEBCFC /* CollectionViewController.swift */,
CC4178791C6EE8C700296FD8 /* CollectionViewCell.swift */,
CC41787B1C6EF39100296FD8 /* UIKit+Changeset.swift */,
CC4178831C6EF88B00296FD8 /* Changeset+Naive.swift */,
29078AC71C895E9F00FBBEC9 /* DataSource.swift */,
CC41786E1C6EE5E000296FD8 /* Assets.xcassets */,
Expand Down Expand Up @@ -330,6 +330,7 @@
buildActionMask = 2147483647;
files = (
29828DE41C2A8BD40056284E /* Changeset.swift in Sources */,
29214F661DE4DF9D000677A7 /* UIKit+Changeset.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -348,7 +349,6 @@
CC4178841C6EF88B00296FD8 /* Changeset+Naive.swift in Sources */,
CC3454AA1C854BEF00CE0C4D /* TableViewController.swift in Sources */,
CC4178681C6EE5E000296FD8 /* AppDelegate.swift in Sources */,
CC41787C1C6EF39100296FD8 /* UIKit+Changeset.swift in Sources */,
CC41787A1C6EE8C700296FD8 /* CollectionViewCell.swift in Sources */,
CCDD53621C7D901F00FEBCFC /* CollectionViewController.swift in Sources */,
29078AC81C895E9F00FBBEC9 /* DataSource.swift in Sources */,
Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ let edits = [
assert(changeset.edits == edits)
```

These index values can be used directly in the animation blocks of `beginUpdates`/`endUpdates` on `UITableView` and `performBatchUpdates` on `UICollectionView` in that `Changeset` follows the principles explained under [_Batch Insertion, Deletion, and Reloading of Rows and Sections_](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW9) in Apple’s [Table View Programming Guide for iOS](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/AboutTableViewsiPhone/AboutTableViewsiPhone.html).

In short; first all deletions and substitutions are made, relative to the source collection, then, relative to the resulting collection, insertions. A move is just a deletion followed by an insertion.

If you don’t want the overhead of `Changeset` itself, which also stores the source and target collections, you can call `edits` directly (here with [example data](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW16) from Apple’s guide):
If you don’t want the overhead of `Changeset` itself, which also stores the source and target collections, you can call `edits` directly (here with [example data](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW16) from Apple’s [Table View Programming Guide for iOS](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/AboutTableViewsiPhone/AboutTableViewsiPhone.html)):

```swift
let source = ["Arizona", "California", "Delaware", "New Jersey", "Washington"]
Expand All @@ -48,14 +44,26 @@ let edits = Changeset.edits(from: source, to: target)
print(edits)
// [insert Alaska at index 0, replace with Georgia at index 2, replace with Virginia at index 4]
```

## UIKit Integration

The index values can be used directly in the animation blocks of `beginUpdates`/`endUpdates` on `UITableView` and `performBatchUpdates` on `UICollectionView` in that `Changeset` follows the principles explained under [_Batch Insertion, Deletion, and Reloading of Rows and Sections_](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW9) in Apple’s guide.

In short; first all deletions and substitutions are made, relative to the source collection, then, relative to the resulting collection, insertions. A move is just a deletion followed by an insertion.

In the iOS framework, two convenience extensions (one on `UITableView` and one on `UICollectionView`) have been included to make animated table/collection view updates a breeze. Just call `update`, like this:

```swift
tableView.update(with: changeset.edits)
```

## Test App

The Xcode project contains a target to illustrate the usage in an app:
The Xcode project also contains a target to illustrate the usage in an app:

![Test App](Test\ App/Screen.png "Test App")
![Test App](Test\ App/Screen.gif "Test App")

This includes simple extensions on `UITableview` and `UICollectionView` making it trivial to animate transitions based on the edits of a `Changeset`.
This uses the extensions mentioned above to animate transitions based on the edits of a `Changeset`.

## License

Expand Down
17 changes: 10 additions & 7 deletions Test App/UIKit+Changeset.swift → Sources/UIKit+Changeset.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//
// UIKit+Changeset.swift
// Changeset
// Copyright (c) 2016 Joachim Bondo. All rights reserved.
//

#if os(iOS)

import UIKit
import Changeset

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) {
open func update<T: Equatable>(with edits: [Edit<T>], in section: Int = 0) {

guard !edits.isEmpty else { return }

let indexPaths = batchIndexPathsFromEdits(edits, inSection: section)
let indexPaths = batchIndexPaths(from: edits, in: section)

self.beginUpdates()
if !indexPaths.deletions.isEmpty { self.deleteRows(at: indexPaths.deletions, with: .automatic) }
Expand All @@ -26,11 +27,11 @@ extension UITableView {
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)? = nil) {
open func update<T: Equatable>(with edits: [Edit<T>], in section: Int = 0, completion: ((Bool) -> Void)? = nil) {

guard !edits.isEmpty else { return }

let indexPaths = batchIndexPathsFromEdits(edits, inSection: section)
let indexPaths = batchIndexPaths(from: edits, in: section)

self.performBatchUpdates({
if !indexPaths.deletions.isEmpty { self.deleteItems(at: indexPaths.deletions) }
Expand All @@ -40,7 +41,7 @@ extension UICollectionView {
}
}

private func batchIndexPathsFromEdits<T: Equatable> (_ edits: [Edit<T>], inSection section: Int) -> (insertions: [IndexPath], deletions: [IndexPath], updates: [IndexPath]) {
private func batchIndexPaths<T: Equatable> (from edits: [Edit<T>], in section: Int) -> (insertions: [IndexPath], deletions: [IndexPath], updates: [IndexPath]) {

var insertions = [IndexPath]()
var deletions = [IndexPath]()
Expand All @@ -64,3 +65,5 @@ private func batchIndexPathsFromEdits<T: Equatable> (_ edits: [Edit<T>], inSecti

return (insertions: insertions, deletions: deletions, updates: updates)
}

#endif
2 changes: 1 addition & 1 deletion Test App/CollectionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CollectionViewController: UICollectionViewController {
@IBAction func test(_ sender: UIBarButtonItem) {
self.dataSource.runTests() {
(edits: [Edit<Character>], isComplete: Bool) in
self.collectionView?.updateWithEdits(edits, inSection: 0)
self.collectionView?.update(with: edits)
sender.isEnabled = isComplete
}
}
Expand Down
Binary file added Test App/Screen.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed Test App/Screen.png
Binary file not shown.
2 changes: 1 addition & 1 deletion Test App/TableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TableViewController: UITableViewController {
@IBAction func test(_ sender: UIBarButtonItem) {
self.dataSource.runTests() {
(edits: [Edit<Character>], isComplete: Bool) in
self.tableView.updateWithEdits(edits, inSection: 0)
self.tableView.update(with: edits)
sender.isEnabled = isComplete
}
}
Expand Down

0 comments on commit 24d2bd8

Please sign in to comment.