Compare Two Version Strings in Swift

Swift: How to compare string version that contains letters

Replace these two lines in your code with the following lines

   var versionComponents = components(separatedBy: versionDelimiter)
.compactMap(Double.init)
.map { String($0) }

var targetComponents = targetVersion.components(separatedBy: versionDelimiter)
.compactMap(Double.init)
.map { String($0) }

And if you need full code to test

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).compactMap(Double.init).map { String($0) }
var targetComponents = targetVersion.components(separatedBy: versionDelimiter).compactMap(Double.init).map { String($0) }

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 }

}

let val = "0.21.16.AC04D0" === "0.21.16"
print(val)

How to compare two strings in swift?

You can try

if !isText.contains("Schreibe etwas...") {
shareButton.isEnabled = true
abortButton.isEnabled = true
}

Compare app versions after update using decimals like 2.5.2

So, I had a similar issue some time back, we needed to be able to compare the installed version with cloud based information and do "things"

The first thing I did was built a concept of a "version", which is based on "major.minor.patch" and "build" properties.

This allowed the cloud to send us a structure which we could understand.

struct Version: Comparable, CustomStringConvertible {

let major: Int
let minor: Int
let patch: Int

let build: Int

init(major: Int, minor: Int, patch: Int, build: Int) {
self.major = major
self.minor = minor
self.patch = patch
self.build = build
}

init(from: String, build: String = "0") {
let buildNumber = Int(build) ?? 0
let parts = from.split(separator: ".")
let major = Int(parts[0]) ?? 0
var minor = 0
var patch = 0
if parts.count >= 2 {
minor = Int(parts[1]) ?? 0
}
if parts.count >= 3 {
patch = Int(parts[2]) ?? 0
}

self.init(major: major, minor: minor, patch: patch, build: buildNumber)
}

var description: String {
return String(format: "%02d.%02d.%02d build %02d", major, minor, patch, build)
}


static func <(lhs: Version, rhs: Version) -> Bool {
return lhs.description.compare(rhs.description, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
}

static func ==(lhs: Version, rhs: Version) -> Bool {
return lhs.description.compare(rhs.description, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedSame
}

}

Add in a simple extensions to get it from the app itself...

extension Version {

static var app: Version = {
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
let build = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
return Version(from: version, build: build)
}()

}

And then you can do things like

if Version.app == Version(from: "2.5.2") {
// And now do some stuff
}

Now, you will need to play around with this, as my needs might not be exactly the same as yours, but this is basically what I was able to use and it worked well, for my needs

But aren't you comparing 2 strings there? What if the user is in version 3.0.0 and I want all users with version 2.5.2 and below to clean cache? Can I do: if Version.app <= Version(from: "2.5.2") { } ?

This is one of those nice little features of Swift (actually ObjC ). Have a look at what NSString.CompareOptions.numeric does for the comparison

For example...

let userVersion = Version(from: "3.0.0")
let targetVersion = Version(from: "2.5.2")

userVersion == targetVersion // 3.0.0 == 2.5.2 - false ✅
userVersion > targetVersion // 3.0.0 > 2.5.2 - true ✅
userVersion < targetVersion // 3.0.0 < 2.5.2 - false ✅
userVersion >= targetVersion // 3.0.0 >= 2.5.2 - true ✅
userVersion <= targetVersion // 3.0.0 <= 2.5.2 - false ✅

How to compare two Strings to check if they have same Characters Swift 4?

If “multiplicity” counts (i.e. "aab" has the same characters as "aba",
but not the same characters as "abb"), then

s1.sorted() == s2.sorted()

does the trick. If you don't care about the multiplicity, then just

Set(s1) == Set(s2)

Example:

let firstArray = ["sumit", "ambuj", "abhi", "aba"]
let secondArray = ["mitsu", "jumba", "hibb", "abb"]

for (s1, s2) in zip(firstArray, secondArray) {
print(s1.sorted() == s2.sorted())
}

// true, true, false, false

for (s1, s2) in zip(firstArray, secondArray) {
print(Set(s1) == Set(s2))
}

// true, true, false, true

For longer strings it might be more efficient to maintain a
dictionary with the number of occurrences of each character in
a string (similar to a NSCountedSet):

func characterCounts(_ s: String) -> [Character: Int] {
return s.reduce(into: [:], { $0[$1, default: 0] += 1 })
}

and then compare the dictionaries:

characterCounts(s1) == characterCounts(s2)

Comparing Strings in Swift

It's not changing because you're redeclaring image11 within each conditional. Change let image11 = ... to image11 = ... to access what I assume is a previously declared version of image11, ex:

if prioridad == sameQuotation {
print("es 0-")
image11 = UIImage(named: "pri0") as UIImage?
}

let sameQuotation1 = "1"
if prioridad == sameQuotation1 {
print("es 1-")
image11 = UIImage(named: "pri1") as UIImage?
}

XCTest fails to compare two strings

As guys wrote in the comments, my textview was adding "Object Replacement Character" or "U+FFFC" after it finished editing.

To make the strings equal, I needed to do this:

let trimmedTypedText = typedText.replacingOccurrences(of: "\u{fffc}", with: "")

So this will now succeed:

if let typedText = myTextView.value as? String {
let trimmedTypedText = typedText.replacingOccurrences(of: "\u{fffc}", with: "")
XCTAssertEqual(trimmedTypedText, text, "The texts are not matching")
}

Swift - Sort array of versions as strings

The easiest option is to use compare with .numeric:

array.sort { $0.compare($1, options: .numeric) == .orderedDescending }

Obviously, if you want it in ascending order, use .orderedAscending.



Related Topics



Leave a reply



Submit