- April 27, 2024
- Mins Read
EditDistance is one of the incremental update tool for UITableView and UICollectionView.
The followings show how this library update UI. They generate the random items and update their UI incrementally.
UITableView | UICollectionView |
---|---|
This library pipelines the process to update UITableView and UICollectionView. It is so difficult to update them incrementally, because iOS app developers need to manage differences between the two DataSources.
If you update items for DataSource:
// dataSource has [“Francis Elton”, “Stanton Denholm”, “Arledge Camden”, “Farland Ridley”, “Alex Helton”]
var nextDataSource = dataSource
// insertion and deletion to data source
nextDataSource.remove(at: 2)
nextDataSource.insert(“Woodruff Chester”, at: 1)
nextDataSource.insert(“Eduard Colby”, at: 3)
Typical code:
// You have to update UITableView according to array’s diff.
dataSource = nextDataSource
tableView.beginUpdates()
tableView.deleteRows(at: [IndexPath(row: 2, section: 0)], with: .fade)
tableView.insertRows(at: [IndexPath(row: 1, section: 0), IndexPath(row: 3, section: 0)], with: .fade)
tableView.endUpdates()
EditDistance takes on that task:
// You don’t need to write insertion and deletion.
let container = dataSource.diff.compare(to: nextDataSource)
dataSource = nextDataSource
tableView.diff.reload(to: container)
All you need is to make the updated array.
You don’t have to manage how to update incrementally. That enables to pileline the process.
EditDistance calculates the difference and converts it into an incremental update of UITableView or UICollectionView.
The difference is based on Edit Distance Algorithm. There are many ways to calculate it and almost all of them nearly run in linear time.
N and M are sequence sizes of each array. D is edit distance and P is the number of deletion.
In our context, Wu’s Algorithm seems to be the best algorithm. It has better performance than the others when your app has many items and adds (or deletes) a few items. (e.g. autopager, access history and notification)
Calculation in this library is not always reasonable to update UI. I recommend that your app calculates edit distance in sub-thread and update UI in main-thread.
> ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
> brew update
> brew install carthage
> touch Cartfile
github “kazuhiro4949/EditDistance”
> carthage update –platform iOS
/usr/local/bin/carthage copy-frameworks
$(SRCROOT)/Carthage/Build/iOS/EditDistance.framework
Import EditDistance
> gem install cocoapods
> pod setup
> pod init
# Uncomment this line to define a global platform for your project
platform :ios, ‘8.0’ # add
use_framework! # add
target ‘MyAppName’ do
pod ‘EditDistance’ # add
end
target ‘MyAppTests’ do
end
target ‘MyAppUITests’
> pod install
open .xcworkspace
let current = [“Francis”, “Woodruff”, “Stanton”]
let next = [“Francis”, “Woodruff”, “Stanton”, “Eduards”]
let proxy = current.diff // => EditDistanceProxy<String>
let container = proxy.compare(to: next) // => EditDistanceContainer<String>
let current = [[“Francis”, “Woodruff”], [“Stanton”]]
let next = [[“Francis”, “Woodruff”], [“Stanton”, “Eduard”]]
let editDistance = EditDistance(from: current, to: next) // => EditDistance<String>
let container = editDistance.calculate() // => EditDistanceContainer<String>
let container = current.diff.compare(to: next, with: DynamicAlgorithm())
to closure
// implement algorithm
let algorithm = AnyEditDistanceAlgorithm { (from, to) -> EditDistanceContainer<String> in
//…
//…
}
let container = current.diff.compare(to: next, with: algorithm)
//implements protocol
public struct Wu<T: Equatable>: EditDistanceAlgorithm {
public typealias Element = T
public func calculate(from: [[T]], to: [[T]]) -> EditDistanceContainer<T> {
//…
//…
}
}
let nextDataSource = [“Francis Elton”, “Woodruff Chester”, “Stanton Denholm”, “Eduard Colby”, “Farland Ridley”, “Alex Helton”]
let container = dataSource.diff.compare(to: nextDataSource)
dataSource = nextDataSource
tableView.diff.reload(with: container)
ataSource = nextDataSource
// tableView.diff.reload(with: container)
tableView.reloadData()
That’s it! 😉
Wu’s algorithm is recommended in this library. The actual speed depends on the number of differences between two arrays and the cost of “==” the elements have. The followings are some avarage speeds for reference. They were executed on iPhone7, iOS 10.2 Simulator and build with “whole module optimization option” setting. The sample arrays are composed of random UUID Strings.
Test Case is here. You can take reexamination with them.
Horizon SDK is a state of the art real-time video recording / photo shooting iOS library. Some of the features ...