2

我在http://snipplr.com/view/2771找到了以下代码

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

Arghhhh 深夜编码,抱歉,我将 10.4 读为 1.4 :(

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

/*
 * 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;
}
4

9 回答 9

2

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

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

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
于 2012-09-06T21:33:19.523 回答
1

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

于 2012-09-06T21:55:34.990 回答
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];
        }
    }
于 2012-09-06T21:57:33.313 回答
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"]);
于 2012-09-06T22:52:59.407 回答
0

我的感觉是第一个数字组总是最重要的,所以 10.anything 大于 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];
于 2012-09-06T23:17:07.580 回答
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");
}
于 2012-10-04T05:11:18.510 回答
0

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

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

于 2012-12-31T12:08:45.537 回答
0

VersionComparator 类很简单

https://github.com/danhanly/VersionComparator

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

于 2014-03-13T17:05:33.053 回答
0

正如这篇文章中所回答的那样;比较 Objective-C 中的版本号

查看我在 github 上实现简单版本检查的 NSString 类别;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"];
于 2014-09-01T18:41:25.760 回答