Comparing version numbers

后端 未结 8 1584
予麋鹿
予麋鹿 2020-12-11 11:39

Some time ago, I read that comparing version numbers can be done using the following code snippet:

NSString *vesrion_1 = @\"1.2.1\";
NSString *version_2 = @\         


        
相关标签:
8条回答
  • 2020-12-11 12:05

    From Apple's documentation:

    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
        // Load resources for iOS 6.1 or earlier
    } 
    else {
        // Load resources for iOS 7 or later
    }
    
    0 讨论(0)
  • 2020-12-11 12:07

    Using NSNumericSearch works in most cases but it fails when version formats are different;

    e.g. when comparing

    [self compareBundleVersion:@"1.1.12" withBundleVersion:@"1.2"];
    

    it will return NSOrderedDescending while it should return NSOrderedAscending.

    Please have a look at my NSString category compareToVersion which handles this in a nice way;

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

    There are also a few helpers;

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

    Check it out at; https://github.com/stijnster/NSString-compareToVersion

    0 讨论(0)
  • 2020-12-11 12:10

    I'd say no, it's not safe. Version numbers are not really numbers but hierarchies of numbers. Consider for instance three version numbers:

    1.19
    1.3
    1.30
    

    A numeric comparison would put 1.19 as being smaller than 1.3 and 1.30. It would also say 1.3 and 1.30 are equal. If the above are version numbers, that is almost certainly not what you want.

    There's also the issue of localisation*. In French, the above would not even parse as numbers.

    It's far better to treat version numbers as what they are, a hierarchy of separate integers. You can easily chop them up with -componentsSeparatedByString:

    *Somewhat ironically, my browser is flagging the British English spelling of localisation as being incorrect.

    0 讨论(0)
  • 2020-12-11 12:18

    I like Mike's (less code) answer but this should also work even if there is a question about the compare option NSNumericSearch works.

    - (NSComparisonResult)compareVersion:(NSString *)versionA to:(NSString *)versionB
    {
       NSArray *versionAComp = [versionA componentsSeparatedByString:@"."];
       NSArray *versionBComp = [versionB componentsSeparatedByString:@"."];
    
       __block NSComparisonResult result = NSOrderedSame;
    
       [versionAComp enumerateObjectsUsingBlock:
       ^(NSString *obj, NSUInteger idx, BOOL *stop)
       {
            // handle abbreviated versions.
            if (idx > versionBComp.count -1)
            {
                *stop = YES;
                return;
            }
    
            NSInteger verAInt = [versionAComp[idx] integerValue];
            NSInteger verBInt = [versionBComp[idx] integerValue];
    
            if (verAInt != verBInt)
            {
                if (verAInt < verBInt)
                    result = NSOrderedAscending;
                else
                    result = NSOrderedDescending;
    
                *stop = YES;
                return;
            }
        }];
       return result; 
    }
    
    0 讨论(0)
  • 2020-12-11 12:19

    In Java you could use the following code snippet to compare versions. If one version number is shorter then the other we normalize it with zeros.

    import java.util.Arrays;
    import java.util.Comparator;
    
    public class FreePlay {
    
        static String[] versions = {"1.5.3.2", "2.3.4", "1.0.3.4", "10.10.1.1", "1.0.2.5", "2.3.4"};
        /**
         * @param args
         */
        public static void main(String[] args) {
            System.out.println("Unsorted versions");
            for (String s: versions) {
                System.out.print("'" + s + "', ");
            }
    
            System.out.println("\nSorted versions");
    
            Arrays.sort(versions, new Comparator<String>() {
    
                @Override
                public int compare(String o1, String o2) {
                    String[] firstVersions = o1.split("\\.");
                    String[] secondVersions = o2.split("\\.");
                    int length = Math.max(firstVersions.length, secondVersions.length);
                    for(int i = 0; i < length; i++) {
                        // normalize the length. If one part is short, we normalize it with zero
                        int firstVersion = i < firstVersions.length ? Integer.parseInt(firstVersions[i]) : 0;
                        int secondVersion = i < secondVersions.length ? Integer.parseInt(secondVersions[i]) : 0;
                        if(firstVersion < secondVersion)
                            return -1;
                        if(firstVersion > secondVersion)
                            return 1;
                    }
                    return 0;
                }});
    
            for (String s: versions) {
                System.out.print("'" + s + "', ");
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-11 12:21

    I don't know of anything built in that will do it, but I have heard that the Sparkle framework has a version comparator.

    Browsing quickly through the source reveals that the SUStandardVersionComparator object seems to be in charge of it. It conforms to the <SUVersionComparison> protocol,which means you could probably just use it like this:

    NSString *versionA = @"1.2.1";
    NSString *versionB = @"1.2.0";
    id <SUVersionComparison> comparator = [SUStandardVersionComparator defaultComparator];
    NSInteger result = [comparator compareVersion:versionA toVersion:versionB];
    if (result == NSOrderedSame) {
      //versionA == versionB
    } else if (result == NSOrderedAscending) {
      //versionA < versionB
    } else {
      //versionA > versionB
    }
    

    (note: code untested and typed in a browser. Caveat Implementor)

    0 讨论(0)
提交回复
热议问题