Сравните номера версий в Objective C

Я пишу приложение, которое получает данные с объектами и номерами версий. Числа отформатированы как "1.0.1" или "1.2.5". Как я могу сравнить эти номера версий? Я думаю, что они должны быть отформатированы как строка сначала, нет? Какие опции я должен решить, что "1.2.5" прибывает после "1.0.1"?

83
задан Josh Caswell 27 October 2016 в 16:58
поделиться

4 ответа

Это самый простой способ сравнения версий, учитывая, что "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
}
230
ответ дан 24 November 2019 в 08:40
поделиться

Если Вы знаете, что каждый номер версии будет иметь ровно 3 целых числа, разделенных точками, Вы можете разобрать их (например, используя sscanf(3)) и сравнить:

const char *version1str = "1.0.1";
const char *version2str = "1.2.5";
int major1, minor1, patch1;
int major2, minor2, patch2;
if(sscanf(version1str, "%d.%d.%d", &major1, &minor1, &patch1) == 3 &&
   sscanf(version2str, "%d.%d.%d", &major2, &minor2, &patch2) == 3)
{
    // Parsing succeeded, now compare the integers
    if(major1 > major2 ||
      (major1 == major2 && (minor1 > minor2 ||
                           (minor1 == minor2 && patch1 > patch2))))
    {
        // version1 > version2
    }
    else if(major1 == major2 && minor1 == minor2 && patch1 == patch2)
    {
        // version1 == version2
    }
    else
    {
        // version1 < version2
    }
}
else
{
    // Handle error, parsing failed
}
0
ответ дан 24 November 2019 в 08:40
поделиться

Glibc имеет функцию strverscmp и versionsort... к сожалению, не переносится на iPhone, но вы можете написать свой собственный довольно легко. Эта (непроверенная) повторная реализация происходит не от чтения исходных текстов Glibc, а от простого чтения документированного поведения.

int strverscmp(const char *s1, const char *s2) {
    const char *b1 = s1, *b2 = s2, *e1, *e2;
    long n1, n2;
    size_t z1, z2;
    while (*b1 && *b1 == *b2) b1++, b2++;
    if (!*b1 && !*b2) return 0;
    e1 = b1, e2 = b2;
    while (b1 > s1 && isdigit(b1[-1])) b1--;
    while (b2 > s2 && isdigit(b2[-1])) b2--;
    n1 = strtol(b1, &e1, 10);
    n2 = strtol(b2, &e2, 10);
    if (b1 == e1 || b2 == e2) return strcmp(s1, s2);
    if (n1 < n2) return -1;
    if (n1 > n2) return 1;
    z1 = strspn(b1, "0"), z2 = strspn(b2, "0");
    if (z1 > z2) return -1;
    if (z1 < z2) return 1;
    return 0;
}
0
ответ дан 24 November 2019 в 08:40
поделиться

Sparkle (самый популярный фреймворк обновления программного обеспечения для MacOS) имеет класс SUStandardVersionComparator, который делает это, а также учитывает номера сборки и бета-маркеры. Т.е. он корректно сравнивает 1.0.5 > 1.0.5b7 или 2.0 (2345) > 2.0 (2100). Код использует только Foundation, поэтому должен прекрасно работать и на iOS.

.
7
ответ дан 24 November 2019 в 08:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: