如何在Objective-C中使用一个数字中较少部分的版本号进行比较?

时间:2012-09-06 21:27:24

标签: iphone objective-c ios

我在http://snipplr.com/view/2771

找到了以下代码

这是非常好的,几乎正是我所寻找的,但如果我使用值@"1.4.5", @"10.4",它会产生错误的结果,说第一个数字较低。

Arghhhh深夜编码,对不起我读了10.4作为1.4 :(

我不确定为什么比较有问题,问题是什么?

/*
 * compareVersions(@"10.4",             @"10.3"); //             
       returns NSOrderedDescending (1) - aka first number is higher

 * compareVersions(@"10.5",             @"10.5.0"); //           
       returns NSOrderedSame (0) 

 * compareVersions(@"10.4 Build 8L127", @"10.4 Build 8P135"); // 
       returns NSOrderedAscending (-1) - aka first number is lower
 */
NSComparisonResult compareVersions(NSString* leftVersion, NSString* rightVersion)
{
    int i;

    // Break version into fields (separated by '.')
    NSMutableArray *leftFields  = [[NSMutableArray alloc] initWithArray:[leftVersion  componentsSeparatedByString:@"."]];
    NSMutableArray *rightFields = [[NSMutableArray alloc] initWithArray:[rightVersion componentsSeparatedByString:@"."]];

    // Implict ".0" in case version doesn't have the same number of '.'
    if ([leftFields count] < [rightFields count]) {
        while ([leftFields count] != [rightFields count]) {
            [leftFields addObject:@"0"];
        }
    } else if ([leftFields count] > [rightFields count]) {
        while ([leftFields count] != [rightFields count]) {
            [rightFields addObject:@"0"];
        }
    }

    // Do a numeric comparison on each field
    for(i = 0; i < [leftFields count]; i++) {
        NSComparisonResult result = [[leftFields objectAtIndex:i] compare:[rightFields objectAtIndex:i] options:NSNumericSearch];
        if (result != NSOrderedSame) {
            [leftFields release];
            [rightFields release];
            return result;
        }
    }

    [leftFields release];
    [rightFields release];  
    return NSOrderedSame;
}

9 个答案:

答案 0 :(得分:2)

[我今天早些时候发布了这个,但它没有被选为答案,它可能更适合您的问题。还有其他技巧,您可以查看herehere以获取其他解决方案。]

我所做的就是把这个字符串分解成组件:

NSArray *array = [myVersion componentsSeparatedByCharactersInSet:@"."];

NSInteger value = 0;
NSInteger multiplier = 1000000;
for(NSString *n in array) {
  value += [n integerValue] * multiplier;
  multiplier /= 100;
}

这样做可以为您提供可用于比较的标准化值,并且通常会比较具有不同“深度”的版本,即1.5和1.5.2。

如果您有超过100个点发布(即任何数字> 100),它会中断,并且还会声明1.5.0 == 1.5。也就是说,它简短,甜美,易于使用。

编辑:如果你使用NSString'compare:options:'方法,请确保你的字符串整齐:

    s1 = @"1.";
    s2 = @"1";
    NSLog(@"Compare %@ to %@ result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
    s1 = @"20.20.0";
    s2 = @"20.20";
    NSLog(@"Compare %@ to %@ result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);

2012-09-06 11:26:24.793 xxx[59804:f803] Compare 1. to 1 result 1
2012-09-06 11:26:24.794 xxx[59804:f803] Compare 20.20.0 to 20.20 result 1

答案 1 :(得分:1)

适用于Mac的Sparkle框架是开源的,它有一些简洁的版本检查代码,您可以查看:https://github.com/andymatuschak/Sparkle/blob/master/SUStandardVersionComparator.m

答案 2 :(得分:0)

所以你想比较10.5到1.4.6,这样10.5被视为0.10.5

如果是这种情况,则需要在分离的版本号的左侧添加“0”数组项

NSComparisonResult compareVersions(NSString* leftVersion, NSString* rightVersion)
{
    int i;

    // Break version into fields (separated by '.')
    NSMutableArray *leftFields  = [[NSMutableArray alloc] initWithArray:[leftVersion  componentsSeparatedByString:@"."]];
    NSMutableArray *rightFields = [[NSMutableArray alloc] initWithArray:[rightVersion componentsSeparatedByString:@"."]];

    // Implict "0" in case version doesn't have the same number of '.'
    if ([leftFields count] < [rightFields count]) {
        while ([leftFields count] != [rightFields count]) {
            [leftFields insertObject:@"0" atIndex:0];
        }
    } else if ([leftFields count] > [rightFields count]) {
        while ([leftFields count] != [rightFields count]) {
            [rightFields insertObject:@"0" atIndex:0];
        }
    }

答案 3 :(得分:0)

我不是100%肯定你在问什么,但是如果你想要排序数字而不管多少个句号“。”您可以在操作系统版本字典中使用NSSortDescriptor编号:

NSArray *originalArray = [NSArray arrayWithObjects:
              [NSDictionary dictionaryWithObject:@"10.4.5" forKey:@"version"],
              [NSDictionary dictionaryWithObject:@"10.5.6" forKey:@"version"],
              [NSDictionary dictionaryWithObject:@"10.6.8" forKey:@"version"],
              [NSDictionary dictionaryWithObject:@"10.8" forKey:@"version"],
              [NSDictionary dictionaryWithObject:@"10.7.1" forKey:@"version"],
              [NSDictionary dictionaryWithObject:@"10.8.2" forKey:@"version"],
              nil];

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"version" ascending:true];
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSLog(@"Lowest to highest: %@", sortedArray);
NSLog(@"Highest OS version: %@",[[sortedArray objectAtIndex:[sortedArray indexOfObject:[sortedArray lastObject]]] objectForKey:@"version"]);

答案 4 :(得分:0)

我的感觉是,第一个数字组总是最重要的,所以10.什么比9.anything.anything更大。如果我是对的,那么解决方案是用零替换点并用零填充右边的较短字符串以匹配较长字符串的长度:

e.g.
9.4   --->  90400  (padded on the right with 00)
8.6.7 --->  80607

这有什么好处,如果我对这个要求不对,可以通过在右边填充较短的字符串来轻松修复算法。

- (NSComparisonResult)compareVersion:(NSString *)vA withVersion:(NSString *)vB {

    NSString *vAPadded = [vA stringByReplacingOccurrencesOfString:@"." withString:@"0"];
    NSString *vBPadded = [vB stringByReplacingOccurrencesOfString:@"." withString:@"0"];

    while (vAPadded.length < vBPadded.length)
        vAPadded = [vAPadded stringByAppendingString:@"0"];

    while (vBPadded.length < vAPadded.length)
        vBPadded = [vBPadded stringByAppendingString:@"0"];

    return [vAPadded intValue] - [vBPadded intValue];
}

如果我对有效数字有要求,请按照以下方式更改打击垫:

vAPadded = [@"0" stringByAppendingString:vAPadded];

答案 5 :(得分:0)

为什么不使用NSString compare:options:NSNumericSearch

NSString *sysVer = [[UIDevice currentDevice] systemVersion];
NSLog(@"%@,%d,%d,%d", sysVer, [sysVer compare:@"1.0" options: NSNumericSearch], [sysVer compare:@"6.0" options: NSNumericSearch],[sysVer compare:@"10.0" options: NSNumericSearch]);
if ([sysVer compare:@"6.0" options: NSNumericSearch]>=NSOrderedSame) {
    NSLog(@"ios 6");
}

答案 6 :(得分:0)

您可以使用我的Version类来帮助您将版本字符串解析为Version对象以便于比较。它支持4个字段版本号,如major.minor.release.build,所有字段都是可选的。此外,它还有一个比较方法,用于comapring两个版本对象。

https://github.com/polatolu/version-ios

答案 7 :(得分:0)

使用VersionComparator Class

很简单

https://github.com/danhanly/VersionComparator

BOOL更大= [VersionComparator isVersion:@“2.0.0”greaterThanVersion:@“1.1.0”];

答案 8 :(得分:0)

正如这篇文章所述; Compare version numbers in Objective-C

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

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

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

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

还增加了助手;

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