EditDistance 0.8.3

EditDistance 0.8.3

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2019年5月
SPM支持SPM

Kazuhiro Hayashi维护。



  • 作者:
  • Kazuhiro Hayashi

editdistancelogo

Platform Platform Swift 4.0 Swift 3.2 License Version Carthage compatible

EditDistance 是为 UITableView 和 UICollectionView 提供的增量更新工具之一。

以下展示了如何使用这个库更新 UI。它生成随机条目,并逐一更新它们的 UI。

UITableView UICollectionView
tableview collectionview 1

是什么意思?

这个库将更新 UITableView 和 UICollectionView 的过程管道化。增量更新它们非常困难,因为 iOS 程序员需要管理两个 DataSource 之间的差异。

如果您更新 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)

典型代码

// 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 承担这个任务

// You don't need to write insertion and deletion.
let container = dataSource.diff.compare(to: nextDataSource)
dataSource = nextDataSource
tableView.diff.reload(to: container) 

您只需要创建更新的数组。

您不需要管理如何增量更新。这使您可以管道化这个过程。

它是如何工作的?

EditDistance 计算差异,并将其转换为 UITableView 或 UICollectionView 的增量更新。

差异基于 编辑距离算法。计算方法有很多,几乎都近似运行在线性时间内。

  • 动态规划 (O(NM))
  • Mayer 算法 (O(ND))
  • Wu 算法 (O(NP))
  • 等等。

NM 是每个数组序列的大小。D 是编辑距离,P 是删除数量。

在我们的背景下,Wu 算法似乎是最好的算法。当您的应用程序有很多项目并且只添加(或删除)几个项目时,它的性能优于其他算法。(例如,自动分页,访问历史和通知)

优缺点

本库中的计算不总是合理地更新UI。我建议你的应用在子线程中计算编辑距离,并在主线程中更新UI。

特色

需求

  • iOS 8.0+
  • Xcode 8.1+
  • Swift 3.0+

安装

Carthage

  • 从Homebrew安装Carthage
> ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
> brew update
> brew install carthage
  • 移动你的项目目录并创建Cartfile
> touch Cartfile
  • 在Cartfile中添加以下行
github "kazuhiro4949/EditDistance"
  • 创建框架
> carthage update --platform iOS
  • 在Xcode中,转到“通用 > 编译阶段 > 链接的框架和库”
  • 将框架添加到你的项目中
  • 添加一个新的运行脚本并将以下代码放入其中
/usr/local/bin/carthage copy-frameworks
  • 在“输入文件”中点击“+”并添加框架路径
$(SRCROOT)/Carthage/Build/iOS/EditDistance.framework
  • 在源文件中编写导入语句
Import EditDistance

CocoaPods

  • 安装CocoaPods
> gem install cocoapods
> pod setup
  • 创建Podfile
> pod init
  • 编辑Podfile
# 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

打开.xcworkspace文件

使用

计算两个数组的差异

一维数组

1. 准备两个数组。

let current = ["Francis", "Woodruff", "Stanton"]
let next = ["Francis", "Woodruff", "Stanton", "Eduards"]

2. 从数组中调用diff创建EditDistanceProxy实例。

let proxy = current.diff // => EditDistanceProxy<String>

3. 实例具有compareTo用来与下一个数组计算差异。

let container = proxy.compare(to: next) // => EditDistanceContainer<String>

二维数组

1. 准备两个数组。

let current = [["Francis", "Woodruff"], ["Stanton"]]
let next = [["Francis", "Woodruff"], ["Stanton", "Eduard"]]

2. 实例化 EditDistance 对象

let editDistance = EditDistance(from: current, to: next) // => EditDistance<String>

3. 该实例具有 compare(to:) 来计算与下一个数组的差异。

let container = editDistance.calculate() // => EditDistanceContainer<String>

定制算法

到预设算法对象

let container = current.diff.compare(to: next, with: DynamicAlgorithm())

到闭包

// 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> {
      //...
      //...
    }
}

对UITableView的增量更新

1. 计算两个数组之间的差异

let nextDataSource = ["Francis Elton", "Woodruff Chester", "Stanton Denholm", "Eduard Colby", "Farland Ridley", "Alex Helton"]
let container = dataSource.diff.compare(to: nextDataSource)

2. 更新数据源和UI

dataSource = nextDataSource
tableView.diff.reload(with: container) 

如果你不再使用这个库

ataSource = nextDataSource
// tableView.diff.reload(with: container) 
tableView.reloadData()

就是这样!😉

性能

该库推荐使用吴氏算法。实际速度取决于两个数组之间差异的数量和元素"=="操作的成本。以下是一些参考平均速度,它们是在iPhone7、iOS 10.2模拟器和启用“整个模块优化选项”设置的情况下执行的。示例数组由随机UUID字符串组成。

  • 从100个项目到120个项目(增加20项),平均:0.001秒
  • 从100个项目到100个项目(增加10项和删除10项),平均:0.001秒
  • 从100个项目到200个项目(增加100项),平均:0.001毫秒
  • 从100个项目到100个项目(增加50项和删除50项),平均:0.001秒
  • 从1000个项目到1050个项目(增加50个),平均:0.003秒
  • 从1000个项目到1000个项目(增加25个,删除25个),平均:0.003秒
  • 从1000个项目到1200个项目(增加200个),平均:0.003秒
  • 从1000个项目到1000个项目(增加100个,删除100个),平均:0.008秒
  • 从10000个项目到10100个项目(增加100个),平均:0.031秒
  • 从10000个项目到10000个项目(增加50个,删除50个),平均:0.032秒
  • 从10000个项目到12000个项目(增加2000个),平均:0.033秒
  • 从10000个项目到10000个项目(增加1000个,删除1000个),平均:0.055秒

测试用例在这里。您可以用它们进行重新审视。

类设计

editdistance

  • EditDistance 是一个用于计算两个输入数组之间的 EditDistanceAlgorithm 的导向器。
  • AnyEditDistanceAlgorithm 是一个用于 EditDistanceAlgorithm 的类型擦除结构。
  • EditDistanceContainer 是一个容器,用于连接算法的结果和视图的更新。
  • EditScriptConverter 是一个命名空间,用于使用对 UIKit 类的一些扩展。
  • EditScriptConverterProxy 是 UITableView 和 UICollectionView 的代理。它有方法来更新项目。

许可证

版权所有(c)2017 Kazuhiro Hayashi

在此特此授予任何获得本软件及其相关文档副本(“软件”)的人无限制地在软件中处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本,并允许向提供软件的人授予这样做,前提是以下条件

上述版权声明和本许可声明应包括在软件的所有副本或主要部分中。

本软件按“现状”提供,不提供任何形式的保证,无论是明示的还是隐含的,包括但不限于适销性、适用于特定目的和无侵权性的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论责任基于合同、侵权或其他原因,是否源自、由或与软件或其使用或任何其他处理有关。