如何在Objective-C中使用一个数字中较少部分的版本号进行比较?
我在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]) { [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; }
[我今天早些时候发布了这个,但它没有被选为答案,它可能更适合您的问题。 还有其他技术,你可以在这里和这里寻找其他解决方案。]
我所做的就是取出该字符串并将其分解为组件:
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
Mac的Sparkle框架是开源的,它有一些简洁的版本检查代码,您可以查看: https : //github.com/andymatuschak/Sparkle/blob/master/SUStandardVersionComparator.m
所以你想比较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]; } }
我不是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"]);
我的感觉是第一个数字组总是最重要的,所以10.什么比9.anything.anything更大。 如果我是对的,那么解决方案是用零替换点并用零填充右侧的较短字符串以匹配较长字符串的长度:
eg 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];
为什么不使用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"); }
您可以使用我的Version类来帮助您将版本字符串解析为Version对象以便于比较。 它支持4个字段版本号,如major.minor.release.build,所有字段都是可选的。 此外,它还有一个用于comapring两个版本对象的比较方法。
使用VersionComparator Class很简单
https://github.com/danhanly/VersionComparator
BOOL更大= [VersionComparator isVersion:@“2.0.0”greaterThanVersion:@“1.1.0”];
正如这篇文章所述; 比较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"];