Ich habe zwei verschiedene App-Versionszeichenfolgen (dh "3.0.1" und "3.0.2").
Wie kann man diese mit Swift vergleichen ?
Ich musste meine Strings in NSStrings konvertieren:
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")
}
extension String { func isVersionNewer(compareVersion: String) -> Bool { if self.compare(compareVersion, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending { return true } return false }
if storeVersion.compare(currentVersion, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending { NSLog("store version is newer") }
Sie müssen es nicht als NSString umwandeln. Das String-Objekt in Swift 3 ist gerade leistungsfähig genug, um Versionen wie unten zu vergleichen.
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
Das obige Beispiel deckt jedoch keine Versionen mit zusätzlichen Nullen ab (Beispiel: "1.0.0" & "1.0").
Daher habe ich alle Arten dieser Erweiterungsmethoden in String erstellt, um den Versionsvergleich mit Swift durchzuführen. Es berücksichtigt zusätzliche Nullen, die ich gesagt habe, ziemlich einfach und wird wie erwartet funktionieren.
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"))
Werfen Sie einen Blick darauf und nehmen Sie alles, was Sie wollen, in mein Beispiel-Erweiterungs-Repository, ohne dass Sie sich um eine Lizenz kümmern müssen.
https://github.com/DragonCherry/VersionCompare
quelle
1.0.1.2
(ich weiß, es sollte existieren, aber es passiert etwas). Ich habe Ihre Erweiterung geändert und die Tests verbessert, um (glaube ich) alle Fälle abzudecken. Außerdem habe ich eine Erweiterung erstellt, die alle unnötigen Zeichen aus der Versionszeichenfolge entfernt. Manchmal kann dies der Fall seinv1.0.1.2
. Sie können alle den Code in den folgenden Logen überprüfen: String - Erweiterung - gist.github.com/endy-s/3791fe5c856cccaabff331fd49356dbf Tests - gist.github.com/endy-s/7cacaa730bf9fd5abf6021e58e962191 Hoffnung , es hilft jemand :)Swift 3 Version
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 Version vergleichen
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())
quelle
Swift 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...") }
quelle
Folgendes funktioniert für mich:
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
quelle
Manchmal entspricht die Länge der storeVersion nicht der Länge der currentVersion. Beispiel: storeVersion ist
3.0.0
jedoch, dass Sie einen Fehler behoben und benannt haben3.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 }
quelle
Mit Swift 3 können Anwendungsversionszeichenfolgen mithilfe der Vergleichsfunktion mit der auf numerisch eingestellten Option verglichen werden.
In diesem String-Programmierhandbuch aus der Dokumentation der Apple-Entwickler finden Sie Beispiele für die Funktionsweise von Objective-C.
Ich habe diese unter https://iswift.org/playground ausprobiert
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
Hoffentlich hilft das!
Wenn Sie Bibliotheken verwenden möchten, verwenden Sie diese, und erfinden Sie das Rad nicht neu. https://github.com/zenangst/Versions
quelle
Sie können dies mit der Methode 'String.compare' tun. Verwenden Sie ComparisonResult, um festzustellen, wann Ihre Version größer, gleich oder kleiner ist.
Beispiel:
"1.1.2".compare("1.1.1").rawValue -> ComparisonResult.orderedDescending "1.1.2".compare("1.1.2").rawValue -> ComparisonResult.orderedSame "1.1.2".compare("1.1.3").rawValue -> ComparisonResult.orderedAscending
quelle
Schrieb eine kleine Swift 3 Klasse, um dies zu tun:
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
quelle
@ DragonCherry-Lösung ist großartig!
Aber leider funktioniert es nicht, wenn die Version so ist
1.0.1.2
(ich weiß, es sollte nicht existieren, aber es passiert etwas).Ich habe Ihre Erweiterung geändert und die Tests verbessert, um (glaube ich) alle Fälle abzudecken. Außerdem habe ich eine Erweiterung erstellt, die alle unnötigen Zeichen aus der Versionszeichenfolge entfernt. Manchmal kann dies der Fall sein
v1.0.1.2
.Sie können den gesamten Code in den folgenden Abschnitten überprüfen:
Hoffe es hilft jedem :)
quelle
Ich habe die Ashok-Version und DragonCherry gemischt:
// 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 } }
Verwenden von:
"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")
quelle
Ihre Verwendung von
NSString
ist der richtige Weg, aber hier ist ein Nicht-Foundation-Versuch zum Spaß:let storeVersion = "3.14.10" let currentVersion = "3.130.10" func versionToArray(version: String) -> [Int] { return split(version) { $0 == "." }.map { // possibly smarter ways to do this $0.toInt() ?? 0 } } storeVersion < currentVersion // false // true lexicographicalCompare(versionToArray(storeVersion), versionToArray(currentVersion))
quelle
Hier ist eine einfache schnelle Struktur
public struct VersionString: Comparable { public let rawValue: String public init(_ rawValue: String) { self.rawValue = rawValue } public static func == (lhs: VersionString, rhs: VersionString) -> Bool { return lhs.rawValue.compare(rhs.rawValue, options: .numeric) == .orderedSame } public static func < (lhs: VersionString, rhs: VersionString) -> Bool { return lhs.rawValue.compare(rhs.rawValue, options: .numeric) == .orderedAscending } }
quelle
Wie wäre es damit:
class func compareVersion(_ ver: String, to toVer: String) -> ComparisonResult { var ary0 = ver.components(separatedBy: ".").map({ return Int($0) ?? 0 }) var ary1 = toVer.components(separatedBy: ".").map({ return Int($0) ?? 0 }) while ary0.count < 3 { ary0.append(0) } while ary1.count < 3 { ary1.append(0) } let des0 = ary0[0...2].description let des1 = ary1[0...2].description return des0.compare(des1, options: .numeric) }
und testen:
func test_compare_version() { XCTAssertEqual(compareVersion("1.0.0", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1.0.0", to: "1.0."), .orderedSame) XCTAssertEqual(compareVersion("1.0.0", to: "1.0"), .orderedSame) XCTAssertEqual(compareVersion("1.0.0", to: "1."), .orderedSame) XCTAssertEqual(compareVersion("1.0.0", to: "1"), .orderedSame) XCTAssertEqual(compareVersion("1.0.0", to: "1.0.1"), .orderedAscending) XCTAssertEqual(compareVersion("1.0.0", to: "1.1."), .orderedAscending) XCTAssertEqual(compareVersion("1.0.0", to: "1.1"), .orderedAscending) XCTAssertEqual(compareVersion("1.0.0", to: "2."), .orderedAscending) XCTAssertEqual(compareVersion("1.0.0", to: "2"), .orderedAscending) XCTAssertEqual(compareVersion("1.0.0", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1.0.", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1.0", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1.", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1", to: "1.0.0"), .orderedSame) XCTAssertEqual(compareVersion("1.0.1", to: "1.0.0"), .orderedDescending) XCTAssertEqual(compareVersion("1.1.", to: "1.0.0"), .orderedDescending) XCTAssertEqual(compareVersion("1.1", to: "1.0.0"), .orderedDescending) XCTAssertEqual(compareVersion("2.", to: "1.0.0"), .orderedDescending) XCTAssertEqual(compareVersion("2", to: "1.0.0"), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "0.9.9"), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "0.9."), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "0.9"), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "0."), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "0"), .orderedDescending) XCTAssertEqual(compareVersion("", to: "0"), .orderedSame) XCTAssertEqual(compareVersion("0", to: ""), .orderedSame) XCTAssertEqual(compareVersion("", to: "1"), .orderedAscending) XCTAssertEqual(compareVersion("1", to: ""), .orderedDescending) XCTAssertEqual(compareVersion("1.0.0", to: "1.0.0.9"), .orderedSame) XCTAssertEqual(compareVersion("1.0.0.9", to: "1.0.0"), .orderedSame) }
quelle
Ich kann verstehen, dass es viele gute Antworten gibt. Hier ist meine Version des Vergleichs der App-Version.
func compareVersions(installVersion: String, storeVersion: String) -> Bool{ // 1.7.5 var installedArr = installVersion.components(separatedBy: ".") var storeArr = storeVersion.components(separatedBy: ".") var isAvailable = false while(installedArr.count < storeArr.count){ installedArr.append("0") } while(storeArr.count < installedArr.count){ storeArr.append("0") } for index in 0 ..< installedArr.count{ if let storeIndex=storeArr[index].toInt(), let installIndex=installedArr[index].toInt(){ if storeIndex > installIndex{ isAvailable = true return isAvailable } } } return isAvailable }
quelle
Hier ist mein Bemühen, alle Fälle von Versionsformaten wie Vergleichen
"10.0"
mit abzudecken."10.0.1"
Lassen Sie mich wissen, wenn ich einen Fall verpasst habe.Hier ist der Kern https://gist.github.com/shamzahasan88/bc22af2b7c96b6a06a064243a02c8bcc . Hoffe es hilft allen.
Und hier ist der Code, wenn jemand meinen Kern nicht bewerten möchte: P.
extension String { // Version format "12.34.39" where "12" is "Major", "34" is "Minor" and "39" is "Bug fixes" // "maximumDigitCountInVersionComponent" is optional parameter determines the maximum length of "Maajor", "Minor" and "Bug Fixes" func shouldUpdateAsCompareToVersion(storeVersion: String, maximumDigitCountInVersionComponent: Int = 5) -> Bool { let adjustTralingZeros: (String, Int)->String = { val, count in return "\(val)\((0..<(count)).map{_ in "0"}.joined(separator: ""))" } let adjustLength: ([String.SubSequence], Int)->[String] = { strArray, count in return strArray.map {adjustTralingZeros("\($0)", count-$0.count)} } let storeVersionSubSequence = storeVersion.split(separator: ".") let currentVersionSubSequence = self.split(separator: ".") let formatter = NumberFormatter() formatter.minimumIntegerDigits = maximumDigitCountInVersionComponent formatter.maximumIntegerDigits = maximumDigitCountInVersionComponent let storeVersions = adjustLength(storeVersionSubSequence, maximumDigitCountInVersionComponent) let currentVersions = adjustLength(currentVersionSubSequence, maximumDigitCountInVersionComponent) var storeVersionString = storeVersions.joined(separator: "") var currentVersionString = currentVersions.joined(separator: "") let diff = storeVersionString.count - currentVersionString.count if diff > 0 { currentVersionString = adjustTralingZeros(currentVersionString, diff) }else if diff < 0 { storeVersionString = adjustTralingZeros(storeVersionString, -diff) } let literalStoreVersion = Int(storeVersionString)! let literalCurrentVersion = Int(currentVersionString)! return literalCurrentVersion < literalStoreVersion } }
Verwendung:
print("33.29".shouldUpdateAsCompareToVersion(storeVersion: "34.23.19")) // true print("35.29".shouldUpdateAsCompareToVersion(storeVersion: "34.23.19")) // false print("34.23.2".shouldUpdateAsCompareToVersion(storeVersion: "34.23.19")) // false print("34.23.18".shouldUpdateAsCompareToVersion(storeVersion: "34.23.19")) // true
quelle
extension String { func compareVersionNumbers(other: String) -> Int { let nums1 = self.split(separator: ".").map({ Int($0) ?? 0 }) let nums2 = other.split(separator: ".").map({ Int($0) ?? 0 }) for i in 0..<max(nums1.count, nums2.count) { let num1 = i < nums1.count ? nums1[i] : 0 let num2 = i < nums2.count ? nums2[i] : 0 if num1 != num2 { return num1 - num2 } } return 0 } }
quelle