比较 Objective-C 中的版本号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1978456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 22:40:25  来源:igfitidea点击:

Compare version numbers in Objective-C

objective-ccomparison

提问by mlecho

I am writing an application that receives data with items and version numbers. The numbers are formatted like "1.0.1" or "1.2.5". How can I compare these version numbers? I think they have to be formatted as a string first, no? What options do I have to determine that "1.2.5" comes after "1.0.1"?

我正在编写一个接收带有项目和版本号的数据的应用程序。数字的格式为“1.0.1”或“1.2.5”。如何比较这些版本号?我认为它们必须先格式化为字符串,不是吗?我有什么选择来确定“1.2.5”在“1.0.1”之后?

回答by Nathan de Vries

This is the simplest way to compare versions, keeping in mind that "1" < "1.0" < "1.0.0":

这是比较版本的最简单方法,请记住“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
}

回答by nikkiauburger

I'll add my method, which compares strictly numeric versions (no a, b, RC etc.) with any number of components.

我将添加我的方法,该方法将严格的数字版本(无 a、b、RC 等)与任意数量的组件进行比较。

+ (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;
}

回答by DonnaLea

This is an expansion to Nathan de Vries answer to address the problem of 1 < 1.0 < 1.0.0 etc.

这是对 Nathan de Vries 回答的扩展,用于解决 1 < 1.0 < 1.0.0 等问题。

First off we can address the problem of extra ".0"'s on our version string with an NSStringcategory:

首先,我们可以使用NSString类别解决版本字符串中额外“.0”的问题:

@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

With the above NSStringcategory we can shorten our version numbers to drop the unnecessary .0's

使用上述NSString类别,我们可以缩短版本号以删除不必要的 .0

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

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

Now we can still use the beautifully simple approach proposed by Nathan de Vries:

现在我们仍然可以使用 Nathan de Vries 提出的非常简单的方法:

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

回答by Peter

I made it myself,use Category..

我自己做的,使用类别..

Source..

来源..

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

Test..

测试..

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

回答by uliwitness

Sparkle(the most popular software update framework for MacOS) has a SUStandardVersionComparatorclass that does this, and also takes into account build numbers and beta markers. I.e. it correctly compares 1.0.5 > 1.0.5b7or 2.0 (2345) > 2.0 (2100). The code only uses Foundation, so should work fine on iOS as well.

Sparkle(最流行的 MacOS 软件更新框架)有一个SUStandardVersionComparator类可以做到这一点,并且还考虑了内部版本号和 beta 标记。即它正确比较1.0.5 > 1.0.5b7or 2.0 (2345) > 2.0 (2100)。该代码仅使用 Foundation,因此在 iOS 上也应该可以正常工作。

回答by Stijnster

Check out my NSString category that implements easy version checking on github; https://github.com/stijnster/NSString-compareToVersion

查看我在 github 上实现简单版本检查的 NSString 类别;https://github.com/stijnster/NSString-compareToVersion

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

This will return a NSComparisonResultwhich is more accurate then using;

这将返回一个NSComparisonResult,它比使用更准确;

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

Helpers are also added;

还添加了助手;

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

回答by Stunner

My iOS library AppUpdateTrackercontains an NSString categoryto perform this sort of comparison. (Implementation is based off DonnaLea's answer.)

我的 iOS 库AppUpdateTracker包含一个NSString 类别来执行这种比较。(实施基于DonnaLea 的回答。)

Usage would be as follows:

用法如下:

[@"1.4" isGreaterThanVersionString:@"1.3"]; // YES
[@"1.4" isLessThanOrEqualToVersionString:@"1.3"]; // NO

Additionally, you can use it to keep track of your app's installation/update status:

此外,您可以使用它来跟踪应用程序的安装/更新状态:

[AppUpdateTracker registerForAppUpdatesWithBlock:^(NSString *previousVersion, NSString *currentVersion) {
    NSLog(@"app updated from: %@ to: %@", previousVersion, currentVersion);
}];
[AppUpdateTracker registerForFirstInstallWithBlock:^(NSTimeInterval installTimeSinceEpoch, NSUInteger installCount) {
    NSLog(@"first install detected at: %f amount of times app was (re)installed: %lu", installTimeSinceEpoch, (unsigned long)installCount);
}];
[AppUpdateTracker registerForIncrementedUseCountWithBlock:^(NSUInteger useCount) {
    NSLog(@"incremented use count to: %lu", (unsigned long)useCount);
}];

回答by bladnman

I thought I'd just share a function I pulled together for this. It is not perfect at all. Please take a look that the examples and results. But if you are checking your own version numbers (which I have to do to manage things like database migrations) then this may help a little.

我想我只是分享一个我为此汇集的功能。它根本不完美。请看一下示例和结果。但是,如果您正在检查自己的版本号(我必须这样做以管理诸如数据库迁移之类的事情),那么这可能会有所帮助。

(also, remove the log statements in the method, of course. those are there to help you see what it does is all)

(当然,也删除方法中的日志语句。这些语句可以帮助您了解它的全部功能)

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

Results:

结果:

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

notice that alpha works but you have to be very careful with it. once you go alpha at some point you cannot extend that by changing any other minor numbers behind it.

请注意 alpha 有效,但您必须非常小心。一旦你在某个时候进入 alpha,你就不能通过改变它后面的任何其他次要数字来扩展它。

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

回答by ioopl

Swift 2.2 Version :

斯威夫特 2.2 版本:

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

Swift 3 Version :

斯威夫特 3 版本:

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

回答by Matloob Hasnain

Here is the swift 4.0 + code for version comparison

这里是 swift 4.0 + 版本比较代码

 let currentVersion = "1.2.0"

 let oldVersion = "1.1.1"

 if currentVersion.compare(oldVersion, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending {
        print("Higher")
    } else {
        print("Lower")
    }