How do you compare two version strings in Swift? For example, how can I check if version “2.2.5” is higher than “2.0.3” or that a version is at least “1.8.5”? As long as your version strings follow a consistent format it turns out to be not too hard.
Version Strings
Version strings can take many formats. They may not follow strict semantic versioning but they typically have at least some recognizable numerical format:
v2.5
1.0.3
4.9a
Parsing the string ourselves is a pain. Luckily the Foundation framework has a method for comparing the order of two strings:
compare(_:options:range:locale:)
We can omit the range and locale parameters. They default to comparing the whole string and the system locale. To compare two numeric strings we need to specify .numeric
for the options. So to compare two versions strings:
let version1 = "1.5"
let version2 = "2.0"
version1.compare(version2, options: .numeric)
The return value is a ComparisonResult
. This is an example of a closed, or frozen, enum with three possible values:
orderedSame
orderedAscending
orderedDescending
For brevity, let’s use a method to wrap the arguments:
func compareNumeric(_ version1: String, _ version2: String) -> ComparisonResult {
return version1.compare(version2, options: .numeric)
}
Some examples of usage:
compareNumeric("1.0","2.0") // ascending
compareNumeric("v2.9","v3.0") // ascending
compareNumeric("1.1.5", "2.0.0") // ascending
compareNumeric("2.1", "2.0") // descending
compareNumeric("2.0.0", "1.0.1") // descending
compareNumeric("2.4", "2.4") // same
compareNumeric("0.0", "0.1a") // ascending
compareNumeric("0.1c", "0.1b") // descending
compareNumeric("2019.4", "2018.5") // descending
Keep It Simple
One caveat, you need to be sure your version strings have a consistent format. For example, comparing two versions with a different format can give surprising results:
compareNumeric("2.0", "2.0.0") // ascending
This can also cause problems with pre-release versioning:
compareNumeric("1.0.0-rc.1", "1.0.0") // descending
compareNumeric("1.0.0-alpha", "1.0.0") // descending
You’ll need to parse or normalize the strings yourself if you expect those types of versions.