Câu hỏi So sánh số phiên bản trong mục tiêu-C


Tôi đang viết một ứng dụng nhận dữ liệu với các mục và số phiên bản. Các số được định dạng như "1.0.1" hoặc "1.2.5". Làm thế nào tôi có thể so sánh các số phiên bản này? Tôi nghĩ rằng họ phải được định dạng như một chuỗi đầu tiên, phải không? Tôi có những lựa chọn nào để xác định rằng "1.2.5" xuất hiện sau "1.0.1"?


75
2017-12-30 04:40


gốc


Nó giúp làm rõ chính xác sơ đồ phiên bản là gì. Một số có thể có định dạng yêu cầu thêm logic. - uchuugaka


Các câu trả lời:


Đây là cách đơn giản nhất để so sánh các phiên bản, lưu ý rằng "1" <"1.0" <"1.0.0":

NSString* requiredVersion = @"1.2.0";
NSString* actualVersion = @"1.1.5";

if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
  // actualVersion is lower than the requiredVersion
}

208
2018-01-02 07:11



Tôi đã sử dụng phương pháp này, và gần đây tôi thấy rằng nó trả về kết quả sai (khi tôi xem xét) khi so sánh với: 2.4.06 với 2.4.4. Tôi tin rằng 2,4.06 nên thấp hơn 2,4,4, nhưng có lẽ tôi sai ... bất kỳ suy nghĩ? - Omer
@Omer: Tại sao 06 và không 6? Tôi nghĩ hầu hết các nhà phát triển sẽ xem xét phiên bản 2.4.06 là phiên bản cao hơn 2.4.4. - Stephen Melvin
Điều này là tốt đẹp và đơn giản nhưng dựa trên một kế hoạch phiên bản rất đơn giản. - uchuugaka
@ScottBerrevoets Tôi chắc chắn sẽ hy vọng đó không phải là cách nó hoạt động, vì điều đó có nghĩa là "1.2.3" nhỏ hơn "1.1.12" (123 <1112)! Như Apple đã nói một cách cẩn thận, "Số trong chuỗi được so sánh bằng cách sử dụng giá trị số". Đó là, bộ số trong mỗi chuỗi sẽ được so sánh (về cơ bản, componentsSeparatedByString tiếp cận). Bạn có thể tự mình kiểm tra @"1.8" so với @"1.7.2.3.55" và thấy rằng 1.8 đi ra phía trước. - dooleyo
NSNumericSearch cho rằng "1.0" nhỏ hơn "1.0.0". Không đủ linh hoạt cho mục đích của tôi. - bobics


Tôi sẽ thêm phương pháp của tôi, so sánh đúng các phiên bản số (không a, b, RC, v.v.) với bất kỳ số lượng thành phần nào.

+ (NSComparisonResult)compareVersion:(NSString*)versionOne toVersion:(NSString*)versionTwo {
    NSArray* versionOneComp = [versionOne componentsSeparatedByString:@"."];
    NSArray* versionTwoComp = [versionTwo componentsSeparatedByString:@"."];

    NSInteger pos = 0;

    while ([versionOneComp count] > pos || [versionTwoComp count] > pos) {
        NSInteger v1 = [versionOneComp count] > pos ? [[versionOneComp objectAtIndex:pos] integerValue] : 0;
        NSInteger v2 = [versionTwoComp count] > pos ? [[versionTwoComp objectAtIndex:pos] integerValue] : 0;
        if (v1 < v2) {
            return NSOrderedAscending;
        }
        else if (v1 > v2) {
            return NSOrderedDescending;
        }
        pos++;
    }

    return NSOrderedSame;
}

15
2018-05-21 22:05





Đây là một sự mở rộng để Nathan de Vries trả lời để giải quyết vấn đề của 1 <1.0 <1.0.0, v.v.

Trước hết, chúng tôi có thể giải quyết vấn đề thêm ".0" trên chuỗi phiên bản của chúng tôi với một NSString thể loại:

@implementation NSString (VersionNumbers)
- (NSString *)shortenedVersionNumberString {
    static NSString *const unnecessaryVersionSuffix = @".0";
    NSString *shortenedVersionNumber = self;

    while ([shortenedVersionNumber hasSuffix:unnecessaryVersionSuffix]) {
        shortenedVersionNumber = [shortenedVersionNumber substringToIndex:shortenedVersionNumber.length - unnecessaryVersionSuffix.length];
    }

    return shortenedVersionNumber;
}
@end

Với các bên trên NSString loại chúng tôi có thể rút ngắn số phiên bản của chúng tôi để thả các .0 không cần thiết

NSString* requiredVersion = @"1.2.0";
NSString* actualVersion = @"1.1.5";

requiredVersion = [requiredVersion shortenedVersionNumberString]; // now 1.2
actualVersion = [actualVersion shortenedVersionNumberString]; // still 1.1.5

Bây giờ chúng ta vẫn có thể sử dụng cách tiếp cận đơn giản đẹp đẽ được đề xuất bởi Nathan de Vries:

if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
  // actualVersion is lower than the requiredVersion
}

10
2017-07-17 18:43



Điều này kết hợp với giải pháp Nathan de Vries là câu trả lời tốt nhất và thanh lịch nhất. - Dalmazio
Điều này sẽ không nói rằng 7.4.2 là một phiên bản cao hơn 7.5? - Tres
@Tres no. Vì NSNumericSearch được chuyển thành tùy chọn, các chuỗi được so sánh dưới dạng số, do đó 7.4.2 <7.5 - DonnaLea


Sparkle (khung công tác cập nhật phần mềm phổ biến nhất cho MacOS) có SUStandardVersionComparator lớp làm điều này, và cũng đưa vào tài khoản xây dựng số và đánh dấu beta. I E. nó so sánh chính xác 1.0.5 > 1.0.5b7 hoặc là 2.0 (2345) > 2.0 (2100). Mã chỉ sử dụng Foundation, vì vậy cũng nên hoạt động tốt trên iOS.


6
2018-01-03 15:54





Tôi tự làm, sử dụng Danh mục ..

Nguồn ..

@implementation NSString (VersionComparison)
- (NSComparisonResult)compareVersion:(NSString *)version{
    NSArray *version1 = [self componentsSeparatedByString:@"."];
    NSArray *version2 = [version componentsSeparatedByString:@"."];
    for(int i = 0 ; i < version1.count || i < version2.count; i++){
        NSInteger value1 = 0;
        NSInteger value2 = 0;
        if(i < version1.count){
            value1 = [version1[i] integerValue];
        }
        if(i < version2.count){
            value2 = [version2[i] integerValue];
        }
        if(value1  == value2){
            continue;
        }else{
            if(value1 > value2){
                return NSOrderedDescending;
            }else{
                return NSOrderedAscending;
            }
        }
    }
    return NSOrderedSame;
}

Kiểm tra..

NSString *version1 = @"3.3.1";
NSString *version2 = @"3.12.1";
NSComparisonResult result = [version1 compareVersion:version2];
switch (result) {
    case NSOrderedAscending:
    case NSOrderedDescending:
    case NSOrderedSame:
         break;
    }

5
2017-09-04 07:55



Tuyệt vời! Đây là ví dụ duy nhất sử dụng NSComparisonResult trên chuỗi này so sánh 7.28.2 & 7.28 một cách chính xác. - CokePokes


Tôi nghĩ tôi sẽ chỉ chia sẻ một chức năng mà tôi đã tập hợp lại cho việc này. Nó không hoàn hảo chút nào. Xin hãy xem các ví dụ và kết quả. Nhưng nếu bạn đang kiểm tra số phiên bản của riêng mình (mà tôi phải làm để quản lý những thứ như di chuyển cơ sở dữ liệu) thì điều này có thể giúp ích một chút.

(Ngoài ra, loại bỏ các báo cáo đăng nhập trong phương thức, tất nhiên. những thứ đó ở đó để giúp bạn xem nó là gì)

Kiểm tra:

[self isVersion:@"1.0" higherThan:@"0.1"];
[self isVersion:@"1.0" higherThan:@"0.9.5"];
[self isVersion:@"1.0" higherThan:@"0.9.5.1"];
[self isVersion:@"1.0.1" higherThan:@"1.0"];
[self isVersion:@"1.0.0" higherThan:@"1.0.1"];
[self isVersion:@"1.0.0" higherThan:@"1.0.0"];

// alpha tests
[self isVersion:@"1.0b" higherThan:@"1.0a"];
[self isVersion:@"1.0a" higherThan:@"1.0b"];
[self isVersion:@"1.0a" higherThan:@"1.0a"];
[self isVersion:@"1.0" higherThan:@"1.0RC1"];
[self isVersion:@"1.0.1" higherThan:@"1.0RC1"];

Các kết quả:

1.0 > 0.1
1.0 > 0.9.5
1.0 > 0.9.5.1
1.0.1 > 1.0
1.0.0 < 1.0.1
1.0.0 == 1.0.0
1.0b > 1.0a
1.0a < 1.0b
1.0a == 1.0a
1.0 < 1.0RC1       <-- FAILURE
1.0.1 < 1.0RC1     <-- FAILURE

nhận thấy rằng alpha hoạt động nhưng bạn phải rất cẩn thận với nó. một khi bạn đi alpha tại một số điểm bạn không thể mở rộng bằng cách thay đổi bất kỳ số nhỏ khác phía sau nó.

Mã số:

- (BOOL) isVersion:(NSString *)thisVersionString higherThan:(NSString *)thatVersionString {

// LOWER
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending) {
    NSLog(@"%@ < %@", thisVersionString, thatVersionString);
    return NO;
}

// EQUAL
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedSame) {
    NSLog(@"%@ == %@", thisVersionString, thatVersionString);
    return NO;
}

NSLog(@"%@ > %@", thisVersionString, thatVersionString);
// HIGHER
return YES;
}

3
2018-03-15 16:27





Kiểm tra danh mục NSString của tôi, thực hiện kiểm tra phiên bản dễ dàng trên github; https://github.com/stijnster/NSString-compareToVersion

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

Điều này sẽ trả về NSComparisonResult đó là chính xác hơn sau đó sử dụng;

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

Người trợ giúp cũng được thêm vào;

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

3
2017-09-01 18:32





Thư viện iOS của tôi AppUpdateTracker chứa một Danh mục NSString để thực hiện loại so sánh này. (Thực hiện dựa trên Câu trả lời của DonnaLea.)


3
2018-01-21 09:51



là v4.21 <4.3? if ([thisVersion isGreaterThanOrEqualToVersionString: @ "4.3"]) - johndpope
Không, 4,21 được coi là lớn hơn 4,3 là 21> 3. Để đáp ứng sự so sánh bình đẳng của bạn, bạn sẽ muốn so sánh 4,21 với 4,30. Xin vui lòng xem các cuộc thảo luận trong các ý kiến ​​của Câu trả lời của Nathan de Vries. - Stunner


Phiên bản Swift 2.2: 

let currentStoreAppVersion = "1.10.2"
let minimumAppVersionRequired = "1.2.2"
if currentStoreAppVersion.compare(minimumAppVersionRequired, options: NSStringCompareOptions.NumericSearch) ==
            NSComparisonResult.OrderedDescending {
            print("Current Store version is higher")
        } else {
            print("Latest New version is higher")
        }

Phiên bản Swift 3: 

let currentStoreVersion = "1.1.0.2"
let latestMinimumAppVersionRequired = "1.1.1"
if currentStoreVersion.compare(laetstMinimumAppVersionRequired, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending {
print("Current version is higher")
} else {
print("Latest version is higher")
}

2
2017-11-15 12:58





Để kiểm tra phiên bản nhanh chóng, bạn có thể sử dụng

switch newVersion.compare(currentversion, options: NSStringCompareOptions.NumericSearch) {
    case .OrderedDescending:
        println("NewVersion available  ")
        // Show Alert Here

    case .OrderedAscending:
        println("NewVersion Not available  ")
    default:
        println("default")
    }

Hy vọng nó có thể hữu ích.


1
2018-03-24 10:30