我有两个不同的应用程序版本字符串(即“3.0.1”和“3.0.2”)。
如何使用Swift进行比较?
最终不得不将我的Strings转换为NSStrings:
if storeVersion.compare(currentVersion, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending {
println("store version is newer")
}
Swift 3
let currentVersion = "3.0.1"
let storeVersion = "3.0.2"
if storeVersion.compare(currentVersion, options: .numeric) == .orderedDescending {
print("store version is newer")
}
func isVersionNewer(compareVersion: String) -> Bool {
if self.compare(compareVersion, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending {
return true
}
return false
}`
- James Laurenstinif storeVersion.compare(currentVersion, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending { NSLog("store version is newer") }
- Chad你不需要将其转换为NSString。在Swift 3中,字符串对象已经足够强大,可以像下面这样比较版本号。
let version = "1.0.0"
let targetVersion = "0.5.0"
version.compare(targetVersion, options: .numeric) == .orderedSame // false
version.compare(targetVersion, options: .numeric) == .orderedAscending // false
version.compare(targetVersion, options: .numeric) == .orderedDescending // true
但是上面的示例并没有涵盖带有额外零的版本。(例如:"1.0.0"和"1.0")
因此,我已经创建了所有这些基于Swift的字符串扩展方法来处理版本比较。它确实考虑到了我所说的额外零,非常简单,将按照您的预期工作。
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThan: "99.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(equalTo: UIDevice.current.systemVersion))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThan: "3.5.99"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThanOrEqualTo: "13.5.99"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThanOrEqualTo: UIDevice.current.systemVersion))
XCTAssertTrue("0.1.1".isVersion(greaterThan: "0.1"))
XCTAssertTrue("0.1.0".isVersion(equalTo: "0.1"))
XCTAssertTrue("10.0.0".isVersion(equalTo: "10"))
XCTAssertTrue("10.0.1".isVersion(equalTo: "10.0.1"))
XCTAssertTrue("5.10.10".isVersion(lessThan: "5.11.5"))
XCTAssertTrue("1.0.0".isVersion(greaterThan: "0.99.100"))
XCTAssertTrue("0.5.3".isVersion(lessThanOrEqualTo: "1.0.0"))
XCTAssertTrue("0.5.29".isVersion(greaterThanOrEqualTo: "0.5.3"))
只需浏览我的示例扩展存储库,并随心所欲地获取,无需考虑许可证问题。
1.0.1.2
时它无法工作(我知道这种情况应该存在,但事情就是这样)。我修改了你的扩展并改进了测试以覆盖(我相信)所有情况。
此外,我创建了一个扩展,可以从版本字符串中删除所有不必要的字符,有时它可能是 v1.0.1.2
。你可以在以下的 gist 中检查所有代码:
字符串扩展 - https://gist.github.com/endy-s/3791fe5c856cccaabff331fd49356dbf
测试 - https://gist.github.com/endy-s/7cacaa730bf9fd5abf6021e58e962191希望能对任何人有所帮助 :) - Endy Silveira"3.1".compare("3.1.0", options: .numeric) == .orderedSame
结果却是false?有什么想法吗?难道我看错了吗? - undefinedSwift 4+
let current = "1.3"
let appStore = "1.2.9"
let versionCompare = current.compare(appStore, options: .numeric)
if versionCompare == .orderedSame {
print("same version")
} else if versionCompare == .orderedAscending {
// will execute the code here
print("ask user to update")
} else if versionCompare == .orderedDescending {
// execute if current > appStore
print("don't expect happen...")
}
Swift 3 版本
let storeVersion = "3.14.10"
let currentVersion = "3.130.10"
extension String {
func versionToInt() -> [Int] {
return self.components(separatedBy: ".")
.map { Int.init($0) ?? 0 }
}
}
//true
storeVersion.versionToInt().lexicographicallyPrecedes(currentVersion.versionToInt())
Swift 2版本比较
let storeVersion = "3.14.10"
let currentVersion = "3.130.10"
extension String {
func versionToInt() -> [Int] {
return self.componentsSeparatedByString(".")
.map {
Int.init($0) ?? 0
}
}
}
// true
storeVersion.versionToInt().lexicographicalCompare(currentVersion.versionToInt())
以下对我有效:
extension String {
static func ==(lhs: String, rhs: String) -> Bool {
return lhs.compare(rhs, options: .numeric) == .orderedSame
}
static func <(lhs: String, rhs: String) -> Bool {
return lhs.compare(rhs, options: .numeric) == .orderedAscending
}
static func <=(lhs: String, rhs: String) -> Bool {
return lhs.compare(rhs, options: .numeric) == .orderedAscending || lhs.compare(rhs, options: .numeric) == .orderedSame
}
static func >(lhs: String, rhs: String) -> Bool {
return lhs.compare(rhs, options: .numeric) == .orderedDescending
}
static func >=(lhs: String, rhs: String) -> Bool {
return lhs.compare(rhs, options: .numeric) == .orderedDescending || lhs.compare(rhs, options: .numeric) == .orderedSame
}
}
"1.2.3" == "1.2.3" // true
"1.2.3" > "1.2.3" // false
"1.2.3" >= "1.2.3" // true
"1.2.3" < "1.2.3" // false
"1.2.3" <= "1.2.3" // true
"3.0.0" >= "3.0.0.1" // false
"3.0.0" > "3.0.0.1" // false
"3.0.0" <= "3.0.0.1" // true
"3.0.0.1" >= "3.0.0.1" // true
"3.0.1.1.1.1" >= "3.0.2" // false
"3.0.15" > "3.0.1.1.1.1" // true
"3.0.10" > "3.0.100.1.1.1" // false
"3.0.1.1.1.3.1.7" == "3.0.1.1.1.3.1" // false
"3.0.1.1.1.3.1.7" > "3.0.1.1.1.3.1" // true
"3.14.10" == "3.130.10" // false
"3.14.10" > "3.130.10" // false
"3.14.10" >= "3.130.10" // false
"3.14.10" < "3.130.10" // true
"3.14.10" <= "3.130.10" // true
// MARK: - Version comparison
extension String {
// Modified from the DragonCherry extension - https://github.com/DragonCherry/VersionCompare
private func compare(toVersion targetVersion: String) -> ComparisonResult {
let versionDelimiter = "."
var result: ComparisonResult = .orderedSame
var versionComponents = components(separatedBy: versionDelimiter)
var targetComponents = targetVersion.components(separatedBy: versionDelimiter)
while versionComponents.count < targetComponents.count {
versionComponents.append("0")
}
while targetComponents.count < versionComponents.count {
targetComponents.append("0")
}
for (version, target) in zip(versionComponents, targetComponents) {
result = version.compare(target, options: .numeric)
if result != .orderedSame {
break
}
}
return result
}
func isVersion(equalTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedSame }
func isVersion(greaterThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedDescending }
func isVersion(greaterThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedAscending }
func isVersion(lessThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedAscending }
func isVersion(lessThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedDescending }
static func ==(lhs: String, rhs: String) -> Bool { lhs.compare(toVersion: rhs) == .orderedSame }
static func <(lhs: String, rhs: String) -> Bool { lhs.compare(toVersion: rhs) == .orderedAscending }
static func <=(lhs: String, rhs: String) -> Bool { lhs.compare(toVersion: rhs) != .orderedDescending }
static func >(lhs: String, rhs: String) -> Bool { lhs.compare(toVersion: rhs) == .orderedDescending }
static func >=(lhs: String, rhs: String) -> Bool { lhs.compare(toVersion: rhs) != .orderedAscending }
}
使用:
"1.2.3" == "1.2.3" // true
"1.2.3" > "1.2.3" // false
"1.2.3" >= "1.2.3" // true
"1.2.3" < "1.2.3" // false
"1.2.3" <= "1.2.3" // true
"3.0.0" >= "3.0.0.1" // false
"3.0.0" > "3.0.0.1" // false
"3.0.0" <= "3.0.0.1" // true
"3.0.0.1" >= "3.0.0.1" // true
"3.0.1.1.1.1" >= "3.0.2" // false
"3.0.15" > "3.0.1.1.1.1" // true
"3.0.10" > "3.0.100.1.1.1" // false
"3.0.1.1.1.3.1.7" == "3.0.1.1.1.3.1" // false
"3.0.1.1.1.3.1.7" > "3.0.1.1.1.3.1" // true
"3.14.10" == "3.130.10" // false
"3.14.10" > "3.130.10" // false
"3.14.10" >= "3.130.10" // false
"3.14.10" < "3.130.10" // true
"3.14.10" <= "3.130.10" // true
"0.1.1".isVersion(greaterThan: "0.1")
"0.1.0".isVersion(equalTo: "0.1")
"10.0.0".isVersion(equalTo: "10")
"10.0.1".isVersion(equalTo: "10.0.1")
"5.10.10".isVersion(lessThan: "5.11.5")
"1.0.0".isVersion(greaterThan: "0.99.100")
"0.5.3".isVersion(lessThanOrEqualTo: "1.0.0")
"0.5.29".isVersion(greaterThanOrEqualTo: "0.5.3")
print("2.0.3".compare("2.0.4", options: .numeric))//orderedAscending
print("2.0.3".compare("2.0.5", options: .numeric))//orderedAscending
print("2.0.4".compare("2.0.4", options: .numeric))//orderedSame
print("2.0.4".compare("2.0.3", options: .numeric))//orderedDescending
print("2.0.5".compare("2.0.3", options: .numeric))//orderedDescending
print("2.0.10".compare("2.0.11", options: .numeric))//orderedAscending
print("2.0.10".compare("2.0.20", options: .numeric))//orderedAscending
print("2.0.0".compare("2.0.00", options: .numeric))//orderedSame
print("2.0.00".compare("2.0.0", options: .numeric))//orderedSame
print("2.0.20".compare("2.0.19", options: .numeric))//orderedDescending
print("2.0.99".compare("2.1.0", options: .numeric))//orderedAscending
希望能对您有所帮助!
如果您喜欢使用库,请使用这个,不要重复造轮子。 https://github.com/zenangst/Versions
3.0.0
,但是您修复了一个错误并将其命名为3.0.0.1
。func ascendingOrSameVersion(minorVersion smallerVersion:String, largerVersion:String)->Bool{
var result = true //default value is equal
let smaller = split(smallerVersion){ $0 == "." }
let larger = split(largerVersion){ $0 == "." }
let maxLength = max(smaller.count, larger.count)
for var i:Int = 0; i < maxLength; i++ {
var s = i < smaller.count ? smaller[i] : "0"
var l = i < larger.count ? larger[i] : "0"
if s != l {
result = s < l
break
}
}
return result
}
我写了一个小的Swift 3类来实现这个功能:
class VersionString: NSObject {
// MARK: - Properties
var string = ""
override var description: String {
return string
}
// MARK: - Initialization
private override init() {
super.init()
}
convenience init(_ string: String) {
self.init()
self.string = string
}
func compare(_ rhs: VersionString) -> ComparisonResult {
return string.compare(rhs.string, options: .numeric)
}
static func ==(lhs: VersionString, rhs: VersionString) -> Bool {
return lhs.compare(rhs) == .orderedSame
}
static func <(lhs: VersionString, rhs: VersionString) -> Bool {
return lhs.compare(rhs) == .orderedAscending
}
static func <=(lhs: VersionString, rhs: VersionString) -> Bool {
return lhs.compare(rhs) == .orderedAscending || lhs.compare(rhs) == .orderedSame
}
static func >(lhs: VersionString, rhs: VersionString) -> Bool {
return lhs.compare(rhs) == .orderedDescending
}
static func >=(lhs: VersionString, rhs: VersionString) -> Bool {
return lhs.compare(rhs) == .orderedDescending || lhs.compare(rhs) == .orderedSame
}
}
let v1 = VersionString("1.2.3")
let v2 = VersionString("1.2.3")
print("\(v1) == \(v2): \(v1 == v2)") // 1.2.3 == 1.2.3: true
print("\(v1) > \(v2): \(v1 > v2)") // 1.2.3 > 1.2.3: false
print("\(v1) >= \(v2): \(v1 >= v2)") // 1.2.3 >= 1.2.3: true
print("\(v1) < \(v2): \(v1 < v2)") // 1.2.3 < 1.2.3: false
print("\(v1) <= \(v2): \(v1 <= v2)") // 1.2.3 <= 1.2.3: true
import Foundation
final class AppVersionComparator {
var currentVersion: String
init() {
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
self.currentVersion = version ?? ""
}
func compareVersions(lhs: String, rhs: String) -> ComparisonResult {
let comparisonResult = lhs.compare(rhs, options: .numeric)
return comparisonResult
}
/**
- If lower bound is present perform lowerBound check
- If upper bound is present perform upperBound check
- Return true if both are nil
*/
func fallsInClosedRange(lowerBound: String?, upperBound: String?) -> Bool {
if let lowerBound = lowerBound {
let lowerBoundComparisonResult = compareVersions(lhs: currentVersion, rhs: lowerBound)
guard lowerBoundComparisonResult == .orderedSame || lowerBoundComparisonResult == .orderedDescending else { return false }
}
if let upperBound = upperBound {
let upperBoundComparisonResult = compareVersions(lhs: currentVersion, rhs: upperBound)
guard upperBoundComparisonResult == .orderedSame || upperBoundComparisonResult == .orderedAscending else { return false }
}
return true
}
/**
- If lower bound is present perform lowerBound check
- If upper bound is present perform upperBound check
- Return true if both are nil
*/
func fallsInOpenRange(lowerBound: String?, upperBound: String?) -> Bool {
if let lowerBound = lowerBound {
let lowerBoundComparisonResult = compareVersions(lhs: currentVersion, rhs: lowerBound)
guard lowerBoundComparisonResult == .orderedDescending else { return false }
}
if let upperBound = upperBound {
let upperBoundComparisonResult = compareVersions(lhs: currentVersion, rhs: upperBound)
guard upperBoundComparisonResult == .orderedAscending else { return false }
}
return true
}
func isCurrentVersionGreaterThan(version: String) -> Bool {
let result = compareVersions(lhs: currentVersion, rhs: version)
return result == .orderedDescending
}
func isCurrentVersionLessThan(version: String) -> Bool {
let result = compareVersions(lhs: currentVersion, rhs: version)
return result == .orderedAscending
}
func isCurrentVersionEqualsTo(version: String) -> Bool {
let result = compareVersions(lhs: currentVersion, rhs: version)
return result == .orderedSame
}}
还有一些测试用例:
import XCTest
class AppVersionComparatorTests: XCTestCase {
var appVersionComparator: AppVersionComparator!
override func setUp() {
super.setUp()
self.appVersionComparator = AppVersionComparator()
}
func testInit() {
XCTAssertFalse(appVersionComparator.currentVersion.isEmpty)
}
func testCompareEqualVersions() {
let testVersions = [VersionComparisonModel(lhs: "1.2.1", rhs: "1.2.1"),
VersionComparisonModel(lhs: "1.0", rhs: "1.0"),
VersionComparisonModel(lhs: "1.0.2", rhs: "1.0.2"),
VersionComparisonModel(lhs: "0.1.1", rhs: "0.1.1"),
VersionComparisonModel(lhs: "3.2.1", rhs: "3.2.1")]
for model in testVersions {
let result = appVersionComparator.compareVersions(lhs: model.lhs, rhs: model.rhs)
XCTAssertEqual(result, .orderedSame)
}
}
func testLHSLessThanRHS() {
let lhs = "1.2.0"
let rhs = "1.2.1"
let result = appVersionComparator.compareVersions(lhs: lhs, rhs: rhs)
XCTAssertEqual(result, .orderedAscending)
}
func testInvalidRange() {
let isCurrentVersionInClosedRange = appVersionComparator.currentVersionFallsInClosedRange(lowerBound: "", upperBound: "")
XCTAssertFalse(isCurrentVersionInClosedRange)
let isCurrentVersionInOpenRange = appVersionComparator.currentVersionFallsInOpenRange(lowerBound: "", upperBound: "")
XCTAssertFalse(isCurrentVersionInOpenRange)
}
func testCurrentInClosedRangeSuccess() {
appVersionComparator.currentVersion = "1.2.1"
let isCurrentVersionInClosedRange = appVersionComparator.currentVersionFallsInClosedRange(lowerBound: "1.2.0", upperBound: "1.2.1")
XCTAssert(isCurrentVersionInClosedRange)
}
func testIsCurrentVersionGreaterThanGivenVersion() {
appVersionComparator.currentVersion = "1.4.2"
let result = appVersionComparator.isCurrentVersionGreaterThan(version: "1.2")
XCTAssert(result)
}
func testIsCurrentVersionLessThanGivenVersion() {
appVersionComparator.currentVersion = "1.4.2"
let result = appVersionComparator.isCurrentVersionLessThan(version: "1.5")
XCTAssert(result)
}
func testIsCurrentVersionEqualsToGivenVersion() {
appVersionComparator.currentVersion = "1.4.2"
let result = appVersionComparator.isCurrentVersionEqualsTo(version: "1.4.2")
XCTAssert(result)
}}
Mock Model:
struct VersionComparisonModel {
let lhs: String
let rhs: String
}
OperatingSystemVersion
使用小数比较应用程序版本更新,如2.5.2 - Leo Dabus