Comparer les numéros de version dans Objective-C

J’écris une application qui reçoit des données avec des éléments et des numéros de version. Les numéros sont formatés comme “1.0.1” ou “1.2.5”. Comment puis-je comparer ces numéros de version? Je pense qu’ils doivent d’abord être formatés en chaîne, non? Quelles options dois-je déterminer que “1.2.5” vient après “1.0.1”?

C’est le moyen le plus simple de comparer les versions, en gardant à l’esprit que “1” <"1.0" <"1.0.0":

NSSsortingng* requiredVersion = @"1.2.0"; NSSsortingng* actualVersion = @"1.1.5"; if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) { // actualVersion is lower than the requiredVersion } 

J’appendai ma méthode, qui compare des versions ssortingctement numériques (non a, b, RC, etc.) avec un nombre quelconque de composants.

 + (NSComparisonResult)compareVersion:(NSSsortingng*)versionOne toVersion:(NSSsortingng*)versionTwo { NSArray* versionOneComp = [versionOne componentsSeparatedBySsortingng:@"."]; NSArray* versionTwoComp = [versionTwo componentsSeparatedBySsortingng:@"."]; 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; } 

Ceci est une extension de la réponse de Nathan de Vries pour résoudre le problème de 1 <1.0 <1.0.0 etc.

Tout d’abord, nous pouvons résoudre le problème des “.0” supplémentaires sur notre chaîne de version avec une catégorie NSSsortingng :

 @implementation NSSsortingng (VersionNumbers) - (NSSsortingng *)shortenedVersionNumberSsortingng { static NSSsortingng *const unnecessaryVersionSuffix = @".0"; NSSsortingng *shortenedVersionNumber = self; while ([shortenedVersionNumber hasSuffix:unnecessaryVersionSuffix]) { shortenedVersionNumber = [shortenedVersionNumber subssortingngToIndex:shortenedVersionNumber.length - unnecessaryVersionSuffix.length]; } return shortenedVersionNumber; } @end 

Avec la catégorie NSSsortingng ci-dessus, nous pouvons raccourcir nos numéros de version pour supprimer les .0 inutiles.

 NSSsortingng* requiredVersion = @"1.2.0"; NSSsortingng* actualVersion = @"1.1.5"; requiredVersion = [requiredVersion shortenedVersionNumberSsortingng]; // now 1.2 actualVersion = [actualVersion shortenedVersionNumberSsortingng]; // still 1.1.5 

Maintenant, nous pouvons toujours utiliser l’approche magnifiquement simple proposée par Nathan de Vries:

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

Sparkle (le framework de mise à jour logicielle le plus populaire pour MacOS) possède une classe SUStandardVersionComparator qui effectue cette opération et prend également en compte les numéros de build et les marqueurs bêta. Par exemple, il compare correctement 1.0.5 > 1.0.5b7 ou 2.0 (2345) > 2.0 (2100) . Le code utilise uniquement Foundation, et devrait donc fonctionner correctement sur iOS.

Je l’ai fait moi-même, utilisez Catégorie ..

La source..

 @implementation NSSsortingng (VersionComparison) - (NSComparisonResult)compareVersion:(NSSsortingng *)version{ NSArray *version1 = [self componentsSeparatedBySsortingng:@"."]; NSArray *version2 = [version componentsSeparatedBySsortingng:@"."]; 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; } 

Tester..

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

Découvrez ma catégorie NSSsortingng qui implémente une vérification de version facile sur github; https://github.com/stijnster/NSSsortingng-compareToVersion

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

Cela retournera un NSComparisonResult qui est plus précis que l’utilisation;

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

Des aides sont également ajoutées;

 [@"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"]; 

Je pensais juste partager une fonction que je rassemblais pour cela. Ce n’est pas parfait du tout. S’il vous plaît jeter un oeil que les exemples et les résultats. Mais si vous vérifiez vos propres numéros de version (ce que je dois faire pour gérer des choses comme les migrations de bases de données), cela peut aider un peu.

(bien sûr, supprimez les instructions du journal dans la méthode. Elles sont là pour vous aider à tout voir)

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"]; 

Résultats:

 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 

remarquez que l'alpha fonctionne, mais vous devez faire très attention avec elle. une fois que vous êtes en alpha à un moment donné, vous ne pouvez pas le prolonger en changeant d'autres nombres mineurs.

Code:

 - (BOOL) isVersion:(NSSsortingng *)thisVersionSsortingng higherThan:(NSSsortingng *)thatVersionSsortingng { // LOWER if ([thisVersionSsortingng compare:thatVersionSsortingng options:NSNumericSearch] == NSOrderedAscending) { NSLog(@"%@ < %@", thisVersionString, thatVersionString); return NO; } // EQUAL if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedSame) { NSLog(@"%@ == %@", thisVersionString, thatVersionString); return NO; } NSLog(@"%@ > %@", thisVersionSsortingng, thatVersionSsortingng); // HIGHER return YES; }