Frage Versionsnummern in Objective-C vergleichen


Ich schreibe eine Anwendung, die Daten mit Artikeln und Versionsnummern empfängt. Die Zahlen sind wie "1.0.1" oder "1.2.5" formatiert. Wie kann ich diese Versionsnummern vergleichen? Ich denke, sie müssen zuerst als String formatiert werden, oder? Welche Optionen muss ich festlegen, dass "1.2.5" nach "1.0.1" kommt?


75
2017-12-30 04:40


Ursprung


Antworten:


Dies ist der einfachste Weg, um Versionen zu vergleichen, wenn man bedenkt, dass "1" <"1.0" <"1.0.0":

NSString* requiredVersion = @"1.2.0";
NSString* actualVersion = @"1.1.5";

if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
  // actualVersion is lower than the requiredVersion
}

208
2018-01-02 07:11



Ich füge meine Methode hinzu, die streng numerische Versionen (keine a, b, RC usw.) mit einer beliebigen Anzahl von Komponenten vergleicht.

+ (NSComparisonResult)compareVersion:(NSString*)versionOne toVersion:(NSString*)versionTwo {
    NSArray* versionOneComp = [versionOne componentsSeparatedByString:@"."];
    NSArray* versionTwoComp = [versionTwo componentsSeparatedByString:@"."];

    NSInteger pos = 0;

    while ([versionOneComp count] > pos || [versionTwoComp count] > pos) {
        NSInteger v1 = [versionOneComp count] > pos ? [[versionOneComp objectAtIndex:pos] integerValue] : 0;
        NSInteger v2 = [versionTwoComp count] > pos ? [[versionTwoComp objectAtIndex:pos] integerValue] : 0;
        if (v1 < v2) {
            return NSOrderedAscending;
        }
        else if (v1 > v2) {
            return NSOrderedDescending;
        }
        pos++;
    }

    return NSOrderedSame;
}

15
2018-05-21 22:05



Dies ist eine Erweiterung von Nathan de Vries Antwort auf das Problem von 1 <1.0 <1.0.0 usw.

Zunächst einmal können wir das Problem von zusätzlichen ".0" s auf unserer Versionsstring mit einem NSString Kategorie:

@implementation NSString (VersionNumbers)
- (NSString *)shortenedVersionNumberString {
    static NSString *const unnecessaryVersionSuffix = @".0";
    NSString *shortenedVersionNumber = self;

    while ([shortenedVersionNumber hasSuffix:unnecessaryVersionSuffix]) {
        shortenedVersionNumber = [shortenedVersionNumber substringToIndex:shortenedVersionNumber.length - unnecessaryVersionSuffix.length];
    }

    return shortenedVersionNumber;
}
@end

Mit dem Obigen NSString Kategorie können wir unsere Versionsnummern verkürzen, um unnötige .0's zu löschen

NSString* requiredVersion = @"1.2.0";
NSString* actualVersion = @"1.1.5";

requiredVersion = [requiredVersion shortenedVersionNumberString]; // now 1.2
actualVersion = [actualVersion shortenedVersionNumberString]; // still 1.1.5

Jetzt können wir noch den schön einfachen Ansatz von Nathan de Vries verwenden:

if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
  // actualVersion is lower than the requiredVersion
}

10
2017-07-17 18:43



Funkeln (das beliebteste Software-Update-Framework für MacOS) hat a SustandardVersionComparator Klasse, die dies tut, und berücksichtigt auch Build-Nummern und Beta-Marker. I.e. es vergleicht es richtig 1.0.5 > 1.0.5b7 oder 2.0 (2345) > 2.0 (2100). Der Code verwendet nur Foundation, sollte also auch auf iOS funktionieren.


6
2018-01-03 15:54



Ich habe es selbst gemacht, benutze Kategorie.

Quelle..

@implementation NSString (VersionComparison)
- (NSComparisonResult)compareVersion:(NSString *)version{
    NSArray *version1 = [self componentsSeparatedByString:@"."];
    NSArray *version2 = [version componentsSeparatedByString:@"."];
    for(int i = 0 ; i < version1.count || i < version2.count; i++){
        NSInteger value1 = 0;
        NSInteger value2 = 0;
        if(i < version1.count){
            value1 = [version1[i] integerValue];
        }
        if(i < version2.count){
            value2 = [version2[i] integerValue];
        }
        if(value1  == value2){
            continue;
        }else{
            if(value1 > value2){
                return NSOrderedDescending;
            }else{
                return NSOrderedAscending;
            }
        }
    }
    return NSOrderedSame;
}

Prüfung..

NSString *version1 = @"3.3.1";
NSString *version2 = @"3.12.1";
NSComparisonResult result = [version1 compareVersion:version2];
switch (result) {
    case NSOrderedAscending:
    case NSOrderedDescending:
    case NSOrderedSame:
         break;
    }

5
2017-09-04 07:55



Ich dachte, ich würde einfach eine Funktion teilen, die ich dafür zusammengestellt habe. Es ist überhaupt nicht perfekt. Bitte werfen Sie einen Blick auf die Beispiele und Ergebnisse. Aber wenn Sie Ihre eigenen Versionsnummern überprüfen (was ich tun muss, um Dinge wie Datenbankmigrationen zu verwalten), kann das ein wenig helfen.

(Entferne natürlich auch die Log-Anweisungen in der Methode. Diese sind da, um zu sehen, was es alles macht.)

Tests:

[self isVersion:@"1.0" higherThan:@"0.1"];
[self isVersion:@"1.0" higherThan:@"0.9.5"];
[self isVersion:@"1.0" higherThan:@"0.9.5.1"];
[self isVersion:@"1.0.1" higherThan:@"1.0"];
[self isVersion:@"1.0.0" higherThan:@"1.0.1"];
[self isVersion:@"1.0.0" higherThan:@"1.0.0"];

// alpha tests
[self isVersion:@"1.0b" higherThan:@"1.0a"];
[self isVersion:@"1.0a" higherThan:@"1.0b"];
[self isVersion:@"1.0a" higherThan:@"1.0a"];
[self isVersion:@"1.0" higherThan:@"1.0RC1"];
[self isVersion:@"1.0.1" higherThan:@"1.0RC1"];

Ergebnisse:

1.0 > 0.1
1.0 > 0.9.5
1.0 > 0.9.5.1
1.0.1 > 1.0
1.0.0 < 1.0.1
1.0.0 == 1.0.0
1.0b > 1.0a
1.0a < 1.0b
1.0a == 1.0a
1.0 < 1.0RC1       <-- FAILURE
1.0.1 < 1.0RC1     <-- FAILURE

Beachten Sie, dass Alpha funktioniert, aber Sie müssen sehr vorsichtig damit sein. Wenn du einmal Alpha benutzt hast, kannst du das nicht mehr verlängern, indem du andere kleine Zahlen dahinter änderst.

Code:

- (BOOL) isVersion:(NSString *)thisVersionString higherThan:(NSString *)thatVersionString {

// LOWER
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending) {
    NSLog(@"%@ < %@", thisVersionString, thatVersionString);
    return NO;
}

// EQUAL
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedSame) {
    NSLog(@"%@ == %@", thisVersionString, thatVersionString);
    return NO;
}

NSLog(@"%@ > %@", thisVersionString, thatVersionString);
// HIGHER
return YES;
}

3
2018-03-15 16:27



Sehen Sie sich meine NSString-Kategorie an, die eine einfache Versionsüberprüfung auf GitHub implementiert; https://github.com/stijnster/NSString-compareToVersion

[@"1.2.2.4" compareToVersion:@"1.2.2.5"];

Dies wird einen zurückgeben NSComparisonResult das ist genauer als die Verwendung;

[@"1.2.2" compare:@"1.2.2.5" options:NSNumericSearch]

Helfer werden ebenfalls hinzugefügt.

[@"1.2.2.4" isOlderThanVersion:@"1.2.2.5"];
[@"1.2.2.4" isNewerThanVersion:@"1.2.2.5"];
[@"1.2.2.4" isEqualToVersion:@"1.2.2.5"];
[@"1.2.2.4" isEqualOrOlderThanVersion:@"1.2.2.5"];
[@"1.2.2.4" isEqualOrNewerThanVersion:@"1.2.2.5"];

3
2017-09-01 18:32



Meine iOS-Bibliothek AppUpdateTracker enthält ein NSString-Kategorie um diese Art von Vergleich durchzuführen. (Die Implementierung basiert auf DonnaLeas Antwort.)


3
2018-01-21 09:51



Swift 2.2 Version: 

let currentStoreAppVersion = "1.10.2"
let minimumAppVersionRequired = "1.2.2"
if currentStoreAppVersion.compare(minimumAppVersionRequired, options: NSStringCompareOptions.NumericSearch) ==
            NSComparisonResult.OrderedDescending {
            print("Current Store version is higher")
        } else {
            print("Latest New version is higher")
        }

Schnelle 3 Version: 

let currentStoreVersion = "1.1.0.2"
let latestMinimumAppVersionRequired = "1.1.1"
if currentStoreVersion.compare(laetstMinimumAppVersionRequired, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending {
print("Current version is higher")
} else {
print("Latest version is higher")
}

2
2017-11-15 12:58