2

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

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

VersionComparator Class で簡単です

https://github.com/danhanly/VersionComparator

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

于 2014-03-13T17:05:33.053 に答える
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

何を求めているのか 100% はわかりませんが、ピリオドの数に関係なく数字を並べ替えたい場合は "." NSSortDescriptorOS バージョンのディクショナリで使用できる数です。

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

簡単に比較できるように、バージョン文字列を Version オブジェクトに解析するのに役立つ Version クラスを使用できます。major.minor.release.build のような 4 つのフィールド バージョン番号をサポートします。すべてのフィールドはオプションです。また、2 つのバージョン オブジェクトを比較するための比較メソッドがあります。

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

于 2012-12-31T12:08:45.537 に答える
0

したがって、10.5 が 0.10.5 と見なされるように、10.5 と 1.4.6 を比較します。

この場合、分離されたバージョン番号の左側に「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 に答える