比较应用程序版本对人类来说是一项简单的任务。您可以立即知道哪个版本较新,例如,2.1.0 高于 1.0.0 和 2.0.0,但是当您尝试在代码中执行此操作时可能并不容易。您可以尝试在字符串拆分的帮助下手动执行此操作。您可能不知道的是,如果您的版本字符串具有一致的格式,您可以将其与在 Foundation 框架中构建的标准 String 方法进行比较。
版本字符串
在这篇文章中,我将重点关注 iOS 版本号。
发布版本号是一个由三个以句点分隔的整数组成的字符串。第一个整数表示应用程序的主要修订,例如实现新功能或主要更改的修订。第二个整数表示实现不太突出的功能的修订版。第三个整数表示维护版本修订。
以下是一些有效的例子:
1.0
1.0.3
2.0.0
可以直接比较
extension String {
func versionCompare(_ otherVersion: String) -> ComparisonResult {
return self.compare(otherVersion, options: .numeric)
}
}
但是会有问题
警告
这种compare(_:options:range:)
方法有一个问题。如果版本相同但格式不同,则会给出错误的比较结果。
"1.0.0".versionCompare("1") // .orderedDescending
"1.0.0".versionCompare("1.0") // .orderedDescending
"1.0.0".versionCompare("1.0.") // .orderedDescending
所以进行了升级:
extension String {
/*
例: sortValue(by:"1.2.3".versionCompare("4"))
*/
func versionCompare(_ otherVersion: String) -> ComparisonResult {
// https://sarunw.com/posts/how-to-compare-two-app-version-strings-in-swift/ --> 博客地址,需要翻墙
let versionDelimiter = "."
// <1> 我们按句点 ( .)拆分版本。
var versionComponents = self.components(separatedBy: versionDelimiter) // 通过"."拆分出 版本数字的数组 ["1", "2", "3"]
var otherVersionComponents = otherVersion.components(separatedBy: versionDelimiter) // 通过"."拆分出 版本数字的数组 ["4"]
// <2> 然后,我们找到我们将零填充的数字差异。
let zeroDiff = versionComponents.count - otherVersionComponents.count // 因为做比较必须格式相同, 位数少的用"0"补位. 此方法为了得到需要补几个"0"
// <3> 如果没有区别,我们不需要做任何事情,使用 simple .compare。
if zeroDiff == 0 {
// Same format, compare normally
return self.compare(otherVersion, options: .numeric)
} else {
//<4> 我们填充一个缺失零的数组。
// 根据 zeroDiff的个数,添加有几个0的数组
let zeros = Array(repeating: "0", count: abs(zeroDiff)) // ["0", "0"]
if zeroDiff > 0 {
// <5> 我们将零填充数组添加到具有更少周期和零的版本中
otherVersionComponents.append(contentsOf: zeros) // 把剩余的不足位数用"0" 补齐 ["4", "0", "0"]
} else {
versionComponents.append(contentsOf: zeros)
}
/*
//<6> 我们使用数组组件从组件构建我们的版本并比较它们。这次它将具有相同的周期和位数。
// 比较类型为 .numeric
详细解析:
1. versionDelimiter = "."
versionComponents.joined(separator: versionDelimiter) ==> "1.2.3"
joined ==> 数组的用法, 通过 "." 把数组中元素拼接成 字符串
2. string.compare(...., options: .numeric)
compare(...) ==> 字符串比较, 比较的类型为数字 .numeric
caseInsensitive 不区分大小写
literal 文字
backwards 向后
anchored 锚定
numeric 数字
*/
return versionComponents.joined(separator: versionDelimiter)
.compare(otherVersionComponents.joined(separator: versionDelimiter), options: .numeric)
}
}
}
如何使用:
sortValue(by:"1.2.3".versionCompare("4")) // .orderedSame
// sortValue(by:"0.0.2".versionCompare("0.0.1")) // .orderedDescending 降序
// sortValue(by:"0.1".versionCompare("0.0.1")) // .orderedDescending
// sortValue(by:"0.1.0".versionCompare("0.0.1")) // .orderedDescending
// sortValue(by:"0.2".versionCompare("0.1")) // .orderedDescending
// sortValue(by:"1.0.0".versionCompare("1.1")) // .orderedAscending 升序
// sortValue(by:"0.1.0".versionCompare("1.0.0")) // .orderedAscending
// sortValue(by:"0.0.1".versionCompare("1.0.0")) // .orderedAscending
// sortValue(by:"0.0.1".versionCompare("1")) // .orderedAscending
// sortValue(by:"1.0".versionCompare("2")) // .orderedAscending
private func sortValue(by type: ComparisonResult) {
switch type {
case .orderedAscending:
print("orderedAscending")
case .orderedSame:
print("orderedSame")
case .orderedDescending:
print("orderedDescending")
}
}