Compare two version strings in Swift

IosSwift

Ios Problem Overview


I have two different app version Strings (i.e. "3.0.1" and "3.0.2").

How can compare these using Swift?

Ios Solutions


Solution 1 - Ios

Ended up having to convert my Strings to 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")
}

Solution 2 - Ios

You don't need to cast it as NSString. String object in Swift 3 is just powerful enough to compare versions like below.

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

But sample above does not cover versions with extra zeros.(Ex: "1.0.0" & "1.0")

So, I've made all kinds of these extension methods in String to handle version comparison using Swift. It does consider extra zeros I said, quite simple and will work as you expected.

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"))

Just take a look and take all you want in my sample extension repository with no license to care about.

https://github.com/DragonCherry/VersionCompare

Solution 3 - Ios

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 compare

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()) 

Solution 4 - Ios

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...")
}

Solution 5 - Ios

The following is working for me:

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

enter image description here

Solution 6 - Ios

Using Swift 3, application version strings can be compare using the compare function with the option set to numeric.

read this String Programming Guide from Apple Developers' documentation for Objective-C examples of how it works.

i tried these at https://iswift.org/playground

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

Hope that helps!

If you like using libraries, use this one, don't reinvent the wheel. https://github.com/zenangst/Versions

Solution 7 - Ios

I have mixed the Ashok version and DragonCherry:

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

}

Using:

"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")

Solution 8 - Ios

Sometimes, the storeVersion's length is not equal to the currentVersion's. e.g. maybe storeVersion is 3.0.0, however, you fixed a bug and named it 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
}

Solution 9 - Ios

You can do it using 'String.compare' method. Use ComparisonResult to identify when your version greater, equal or less.

Example:

"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

Solution 10 - Ios

Wrote a small Swift 3 class to do this:

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

Solution 11 - Ios

@DragonCherry solution is great!

But, unfortunately, it doesn't work when the version is like 1.0.1.2 (I know, it shouldn't exist, but things happens).

I changed your extension and improved the tests to cover (I believe) all cases. Also, I created an extension that removes all the unnecessary characters from the version string, sometimes it can be v1.0.1.2.

You can check all the code in the following gists:

Hope it helps anyone :)

Solution 12 - Ios

I ended up creating below class for my project. Sharing it here, in case it helps someone. Cheers ...!!

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
}}

Some test cases too:

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 

}

Solution 13 - Ios

Your use of NSString is the right way to go, but here is a non-Foundation attempt for fun:

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))

Solution 14 - Ios

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
    }
}

Solution 15 - Ios

Here is a simple swift struct

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
    }
}

Solution 16 - Ios

I can understand there are many good answers given. Here is my version of comparison of 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
    }

Solution 17 - Ios

Here is my effort to cover all cases of version formats like compare "10.0" with "10.0.1", let me know if I have missed any case.

Here is the gist https://gist.github.com/shamzahasan88/bc22af2b7c96b6a06a064243a02c8bcc. Hope it helps everyone.

And here is the code if anyone don't want to rate my gist :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
    }
}

Usage:

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

Solution 18 - Ios

extension String {
    func versionCompare(_ otherVersion: String) -> ComparisonResult {
        let versionDelimiter = "."

        var versionComponents = self.components(separatedBy: versionDelimiter) // <1>
        var otherVersionComponents = otherVersion.components(separatedBy: versionDelimiter)

        let zeroDiff = versionComponents.count - otherVersionComponents.count // <2>

        if zeroDiff == 0 { // <3>
            // Same format, compare normally
            return self.compare(otherVersion, options: .literal)
        } else {
            let zeros = Array(repeating: "0", count: abs(zeroDiff)) // <4>
            if zeroDiff > 0 {
                otherVersionComponents.append(contentsOf: zeros) // <5>
            } else {
                versionComponents.append(contentsOf: zeros)
            }
            return versionComponents.joined(separator: versionDelimiter)
                .compare(otherVersionComponents.joined(separator: versionDelimiter), options: .literal) // <6>
        }
    }
}

//USAGE

let previousVersionNumber = "1.102.130"
let newAnpStoreVersion = "1.2" // <- Higher

switch previousVersionNumber.versionCompare(newAnpStoreVersion) {
case .orderedAscending:
case .orderedSame:
case .orderedDescending:
}

Solution 19 - Ios

How about this:

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)
}

and test:

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)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncodemanView Question on Stackoverflow
Solution 1 - IoscodemanView Answer on Stackoverflow
Solution 2 - IosDragonCherryView Answer on Stackoverflow
Solution 3 - IosWaneView Answer on Stackoverflow
Solution 4 - IosPinkeshGjrView Answer on Stackoverflow
Solution 5 - IosAshokView Answer on Stackoverflow
Solution 6 - IoscomputingfreakView Answer on Stackoverflow
Solution 7 - IosMickael BelhassenView Answer on Stackoverflow
Solution 8 - IosHamGuyView Answer on Stackoverflow
Solution 9 - IosKonstantine DementievView Answer on Stackoverflow
Solution 10 - IosAlex KoshyView Answer on Stackoverflow
Solution 11 - IosEndy SilveiraView Answer on Stackoverflow
Solution 12 - IosPranav GuptaView Answer on Stackoverflow
Solution 13 - IosAirspeed VelocityView Answer on Stackoverflow
Solution 14 - IoshasanView Answer on Stackoverflow
Solution 15 - IosNikolai IschukView Answer on Stackoverflow
Solution 16 - IosUsman AwanView Answer on Stackoverflow
Solution 17 - IosHamza HasanView Answer on Stackoverflow
Solution 18 - IosKurt LaneView Answer on Stackoverflow
Solution 19 - Ioswinner.ktwView Answer on Stackoverflow