Làm cách nào để kiểm tra phiên bản iOS?


848

Tôi muốn kiểm tra xem iOSphiên bản của thiết bị có lớn hơn 3.1.3 tôi đã thử những thứ như:

[[UIDevice currentDevice].systemVersion floatValue]

nhưng nó không hoạt động, tôi chỉ muốn một:

if (version > 3.1.3) { }

Làm thế nào tôi có thể đạt được điều này?


5
Người điều hành Lưu ý : Theo thời gian, câu hỏi này đã tích lũy được hơn 30 câu trả lời. Trước khi thêm câu trả lời mới, hãy chắc chắn rằng giải pháp của bạn chưa được cung cấp.
Matt

3
Bắt đầu Xcode 7, if #available(iOS 9, *) {}trong Swift. Bắt đầu Xcode 9, if (@available(iOS 11, *)) {}trong mục tiêu-c.
Cœur

Câu trả lời:


1002

Câu trả lời nhanh chóng


Kể từ Swift 2.0, bạn có thể sử dụng #availabletrong ifhoặc guardđể bảo vệ mã chỉ nên chạy trên một số hệ thống nhất định.

if #available(iOS 9, *) {}


Trong Objective-C, bạn cần kiểm tra phiên bản hệ thống và thực hiện so sánh.

[[NSProcessInfo processInfo] operatingSystemVersion] trong iOS 8 trở lên.

Kể từ Xcode 9:

if (@available(iOS 9, *)) {}


Câu trả lời đầy đủ

Trong Objective-C và Swift trong những trường hợp hiếm hoi, tốt hơn hết là tránh dựa vào phiên bản hệ điều hành như một dấu hiệu cho thấy khả năng của thiết bị hoặc hệ điều hành. Thường có một phương pháp đáng tin cậy hơn để kiểm tra xem một tính năng hoặc lớp cụ thể có sẵn hay không.

Kiểm tra sự hiện diện của API:

Ví dụ: bạn có thể kiểm tra xem UIPopoverControllercó khả dụng trên thiết bị hiện tại hay không bằng cách sử dụng NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

Đối với các lớp được liên kết yếu, việc gửi tin nhắn trực tiếp đến lớp là an toàn. Đáng chú ý, điều này hoạt động cho các khung không được liên kết rõ ràng là "Bắt buộc". Đối với các lớp bị thiếu, biểu thức ước tính đến 0, không đạt điều kiện:

if ([LAContext class]) {
    // Do something
}

Một số lớp, như CLLocationManagerUIDevice, cung cấp các phương thức để kiểm tra khả năng của thiết bị:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Kiểm tra sự hiện diện của các biểu tượng:

Rất hiếm khi, bạn phải kiểm tra sự hiện diện của hằng số. Điều này xuất hiện trong iOS 8 với việc giới thiệu UIApplicationOpenSettingsURLString, được sử dụng để tải ứng dụng Cài đặt qua -openURL:. Giá trị không tồn tại trước iOS 8. Việc chuyển số không vào API này sẽ bị sập, do đó bạn phải cẩn thận để xác minh sự tồn tại của hằng số trước tiên:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

So sánh với phiên bản hệ điều hành:

Giả sử bạn phải đối mặt với nhu cầu tương đối hiếm để kiểm tra phiên bản hệ điều hành. Đối với các dự án nhắm mục tiêu iOS 8 trở lên, NSProcessInfobao gồm một phương pháp để thực hiện so sánh phiên bản với ít khả năng xảy ra lỗi hơn:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Các dự án nhắm mục tiêu hệ thống cũ có thể sử dụng systemVersiontrên UIDevice. Apple sử dụng nó trong mã mẫu GLSprite của họ .

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

Nếu vì bất kỳ lý do gì bạn quyết định đó systemVersionlà những gì bạn muốn, hãy đảm bảo coi nó là một chuỗi hoặc bạn có nguy cơ cắt bớt số sửa đổi bản vá (ví dụ: 3.1.2 -> 3.1).


161
Có những trường hợp cụ thể trong đó kiểm tra phiên bản hệ thống được bảo hành. Ví dụ: một vài lớp và phương thức riêng tư n 3.x đã được công khai trong 4.0, vì vậy nếu bạn chỉ cần kiểm tra tính khả dụng của chúng, bạn sẽ nhận được kết quả sai trong 3.x. Ngoài ra, cách UIScrollViews xử lý các tỷ lệ thu phóng thay đổi tinh tế trong phiên bản 3.2 trở lên, do đó bạn cần kiểm tra các phiên bản HĐH để xử lý kết quả một cách phù hợp.
Brad Larson

2
iOS 3.2 không xuất hiện để gửi -viewWillAppeartrong a UISplitViewController. Cách hack của tôi là xác định xem <iOS 4.0 và tự gửi nó đến Trình điều khiển Chế độ xem chi tiết trong Root View -didSelectRowAtIndexPath.
jww

10
Bạn cần phải cẩn thận một chút ở đây vì [@"10.0" compare:@"10" options:NSNumericSearch]lợi nhuận NSOrderedDescending, có thể hoàn toàn không có ý định. (Tôi có thể mong đợi NSOrderedSame.) Đây ít nhất là một khả năng lý thuyết.
SK9

Đúng, tôi vừa gặp phải trường hợp cần phải sửa lỗi iOS 5. respondsToSelectoret al sẽ không làm công việc - phải so sánh các phiên bản.
Hot Licks 15/03/13

2
Với sự ra đời của TVos, điều này thậm chí còn trở nên quan trọng hơn. Xem như TVos sẽ trả về 9.0 trong khi SDK 9.1 được sử dụng. Vì vậy, kiểm tra lớp hoặc phương thức (bộ chọn) là cách tốt nhất, sau này bạn nên kiểm tra NSFoundationVersionNumbervà chỉ khi điều đó là không thể, bạn nên kiểm tra các phiên bản hệ thống trên UIDevice.
RCkoenes

1055
/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
    ...
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}

20
+1. Giữ điều này trong một tiêu đề mà bạn có thể bao gồm khi cần là giải pháp đơn giản nhất tôi có thể nghĩ đến. Trong một số trường hợp, điều này đáng tin cậy hơn là kiểm tra tính khả dụng bằng NSClassFromString. Một ví dụ khác là trong iAd, trong đó nếu bạn sử dụng ADBannerContentSizeIdentifierPort Eo trong phiên bản trước 4.2, bạn sẽ nhận được EXEC_BAD_ACCESS, nhưng ADBannerContentSizeIdentifier320x50 không được chấp nhận sau 4.1.
Rab

1
Một nơi khác tôi sử dụng là với UIPageViewControll và đặt kiểu thành UIPageViewControllTransitionStyleScroll trong iOS6.
Paul de Lange

7
Điều này không hoạt động trong 10 giây. Ví dụ, so sánh 4.10 và 4.9 sẽ cho kết quả sai.
pzulw

7
Người ta phải rất cẩn thận khi sử dụng .0số tùy chọn . Ví dụ SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")cho kết quả không chính xác trên iOS 7.0.
Yan

1
Tôi vừa thử nghiệm đưa tệp này vào tệp .pch của mình và nó hoạt động rất tốt (ít nhất là xây dựng với Xcode 5)
whyoz

253

Theo đề xuất của các tài liệu chính thức của Apple : bạn có thể sử dụng NSFoundationVersionNumber, từ NSObjCRuntime.htệp tiêu đề.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}

40
+1 Đây thực tế là lựa chọn an toàn và chính xác nhất ở đây.
mxcl

8
Ừm .. NSFoundationVersionNumber_iOS_6_1không tồn tại trong SDK iOS 5.
Kjuly

2
@Kjuly bạn có thể tự xác định các phiên bản bị thiếu: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (hãy xem dòng 102-130)
CarlJ

3
không, bạn đã sai, NSFoundationVersionNumber_iOS_7_0 không tồn tại. Nhưng tốt, chúng ta có thể định nghĩa nó với #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Để tránh rối tung như thế, tôi đã đi với SYSTEM_VERSION_LESS_THAN (v) vĩ mô từ yasirmturk
Cœur

7
Không, nhưng apple sẽ thêm NSFoundationVersionNumber_iOS_8_0vào iOS 9. chỉ cần kiểm tra NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ

111

Bắt đầu Xcode 9, trong Objective-C :

if (@available(iOS 11, *)) {
    // iOS 11 (or newer) ObjC code
} else {
    // iOS 10 or older code
}

Bắt đầu Xcode 7, trong Swift :

if #available(iOS 11, *) {
    // iOS 11 (or newer) Swift code
} else {
    // iOS 10 or older code
}

Đối với phiên bản, bạn có thể chỉ định MAJOR, MINOR hoặc PATCH (xem http://semver.org/ để biết định nghĩa). Ví dụ:

  • iOS 11iOS 11.0là cùng một phiên bản tối thiểu
  • iOS 10, iOS 10.3 , iOS 10.3.1Là phiên bản tối thiểu khác nhau

Bạn có thể nhập giá trị cho bất kỳ hệ thống nào trong số đó:

  • iOS, macOS,watchOS ,tvOS

Ví dụ trường hợp thực được lấy từ một trong các nhóm của tôi :

if #available(iOS 10.0, tvOS 10.0, *) {
    // iOS 10+ and tvOS 10+ Swift code
} else {
    // iOS 9 and tvOS 9 older code
}

tài liệu


Làm thế nào điều này có thể được đảo ngược trong cả Objective-C hoặc Swift?
Legoless

@Legolessif (...) {} else { ... }
Cœur

Tôi có thể sử dụng guardtrong Objective-C thay vì để khối mở và thụt lề trong elsecâu lệnh không?
Legoless

@Legoless không, chỉ cần sử dụng một ifkhối trống theo sau là một else.
Cœur

1
Đó là giải pháp tôi hiện đang có, chỉ muốn tránh thụt đầu dòng không cần thiết và ifcác khối trống .
Legoless

45

Điều này được sử dụng để kiểm tra phiên bản SDK tương thích trong Xcode, đây là nếu bạn có một nhóm lớn với các phiên bản Xcode khác nhau hoặc nhiều dự án hỗ trợ các SDK khác nhau có chung mã:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
  //programming in iOS 8+ SDK here
#else
  //programming in lower than iOS 8 here   
#endif

Điều bạn thực sự muốn là kiểm tra phiên bản iOS trên thiết bị. Bạn có thể làm điều đó với điều này:

if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
  //older than iOS 8 code here
} else {
  //iOS 8 specific code here
}

Phiên bản Swift:

if let version = Float(UIDevice.current.systemVersion), version < 9.3 {
    //add lower than 9.3 code here
} else {
    //add 9.3 and above code here
}

Các phiên bản hiện tại của swift nên được sử dụng này:

if #available(iOS 12, *) {
    //iOS 12 specific code here
} else {
    //older than iOS 12 code here
}

37

Thử:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}

2
Tại sao không đảo ngược thứ tự ở đây và lưu một so sánh, vì cả @ "3.1.3" và systemVersion đều là NSStrings? Tức là: `if ([@" 3.1.3 "so sánh: [UIDevice currentDevice] .systemVersion tùy chọn: NSNumericSearch] == NSOrderedDesceinating); // Phiên bản hệ điều hành> = 3.1.3 khác; // Phiên bản hệ điều hành <3.1.3`
Cướp

3
Làm điều đó có thể làm cho logic ít rõ ràng hơn. Các hoạt động nên tương đương, tuy nhiên.
Jonathan Grynspan

1
Một so sánh giữa hai số nguyên chắc chắn không phải là rất tốn kém.
KPM

Đó thực sự là một vấn đề về phong cách. Chi phí hoạt động của thông điệp sẽ lớn hơn nhiều so với số nguyên bổ sung.
Jonathan Grynspan

35

Phương pháp tiếp cận ưa thích

Trong Swift 2.0, Apple đã thêm kiểm tra tính khả dụng bằng cú pháp thuận tiện hơn nhiều (Đọc thêm tại đây ). Bây giờ bạn có thể kiểm tra phiên bản HĐH với cú pháp sạch hơn:

if #available(iOS 9, *) {
    // Then we are on iOS 9
} else {
    // iOS 8 or earlier
}

Đây là ưu tiên hơn kiểm tra respondsToSelectorvv ( Có gì mới trong Swift ). Bây giờ trình biên dịch sẽ luôn cảnh báo bạn nếu bạn không bảo vệ mã của mình đúng cách.


Trước Swift 2.0

Tính năng mới trong iOS 8 đang NSProcessInfocho phép kiểm tra phiên bản ngữ nghĩa tốt hơn.

Triển khai trên iOS 8 trở lên

Đối với các mục tiêu triển khai tối thiểu từ iOS 8.0 trở lên, hãy sử dụng NSProcessInfo operatingSystemVersionhoặc isOperatingSystemAtLeastVersion.

Điều này sẽ mang lại những điều sau đây:

let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)
if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {
    //current version is >= (8.1.2)
} else {
    //current version is < (8.1.2)
}

Triển khai trên iOS 7

Đối với mục tiêu triển khai tối thiểu là iOS 7.1 hoặc thấp hơn, sử dụng so sánh với NSStringCompareOptions.NumericSearchtrên UIDevice systemVersion.

Điều này sẽ mang lại:

let minimumVersionString = "3.1.3"
let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)
switch versionComparison {
    case .OrderedSame, .OrderedDescending:
        //current version is >= (3.1.3)
        break
    case .OrderedAscending:
        //current version is < (3.1.3)
        fallthrough
    default:
        break;
}

Đọc thêm tại NSHipster .


9

Tôi luôn giữ những thứ đó trong tệp Constants.h của mình:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES) 
#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

Tuyệt quá. Tốt hơn là đặt nó trong .pchtệp của Dự án XCode của bạn
Vaibhav Jhaveri

1
Tôi đặt tất cả các hằng số của mình trong Constants.htệp được nhập vào pchtệp của mình .
Segev

6
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{

// eg  NSString *reqSysVer = @"4.0";


  NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

  if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
  {
    return YES;
  }else{
    return NO;
  }


}

Thời gian @Jef không phải là dấu thập phân trong phiên bản và có liên quan. Câu trả lời của bạn không bỏ qua các giai đoạn, Nó sẽ thất bại nếu nó đã làm. Trong phiên bản, mỗi phần tử được phân tách là một số đầy đủ. Ví dụ: '1,23,45' lớn hơn '1,2.345' do phần tử thứ hai '23' lớn hơn '2'. Nếu bạn loại bỏ các khoảng thời gian, nó sẽ là cùng một số.
Andres Canella 7/07/2015

6

Với lớp Phiên bản có trong dự án phiên bản nv-ios (Giấy phép Apache, Phiên bản 2.0), thật dễ dàng để lấy và so sánh phiên bản iOS. Một mã ví dụ bên dưới kết xuất phiên bản iOS và kiểm tra xem phiên bản lớn hơn hoặc bằng 6.0.

// Get the system version of iOS at runtime.
NSString *versionString = [[UIDevice currentDevice] systemVersion];

// Convert the version string to a Version instance.
Version *version = [Version versionWithString:versionString];

// Dump the major, minor and micro version numbers.
NSLog(@"version = [%d, %d, %d]",
    version.major, version.minor, version.micro);

// Check whether the version is greater than or equal to 6.0.
if ([version isGreaterThanOrEqualToMajor:6 minor:0])
{
    // The iOS version is greater than or equal to 6.0.
}

// Another way to check whether iOS version is
// greater than or equal to 6.0.
if (6 <= version.major)
{
    // The iOS version is greater than or equal to 6.0.
}

Trang dự án: phiên bản
nv-ios TakahikoKawasaki / nv-ios-phiên bản

Blog: Nhận và so sánh phiên bản iOS khi chạy với lớp Phiên bản
Nhận và so sánh phiên bản iOS khi chạy với lớp Phiên bản


5

Cách mới để kiểm tra phiên bản hệ thống bằng cách sử dụng nhanh chóng Quên [[UIDevice currentDevice] systemVersion] và NSFoundationVersionNumber.

Chúng tôi có thể sử dụng NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false

5

UIDevice + IOSVersion.h

@interface UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion

@end

UIDevice + IOSVersion.m

#import "UIDevice+IOSVersion.h"

@implementation UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;
}

+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedDescending;
}

+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;
}

@end

4

Nói chung, tốt hơn là hỏi xem một đối tượng có thể thực hiện một bộ chọn đã cho hay không, thay vì kiểm tra số phiên bản để quyết định xem nó có phải không.

Khi đây không phải là một lựa chọn, bạn cần phải cẩn thận một chút ở đây vì [@"5.0" compare:@"5" options:NSNumericSearch]lợi nhuận NSOrderedDescendinghoàn toàn không được dự định; Tôi có thể mong đợi NSOrderedSameở đây. Điều này ít nhất là một mối quan tâm về mặt lý thuyết, một điều đáng để bảo vệ chống lại theo ý kiến ​​của tôi.

Cũng đáng xem xét là khả năng của một phiên bản đầu vào xấu mà không thể so sánh hợp lý với. Apple cung cấp ba hằng số xác định trước NSOrderedAscending, NSOrderedSameNSOrderedDescendingnhưng tôi có thể nghĩ đến việc sử dụng đối với một số điều được gọi làNSOrderedUnordered trong trường hợp tôi không thể so sánh hai điều và tôi muốn trả về một giá trị chỉ này.

Hơn nữa, không phải ngày nào Apple cũng sẽ mở rộng ba hằng số được xác định trước của họ để cho phép nhiều giá trị trả về, tạo ra sự so sánh != NSOrderedAscendingkhông khôn ngoan.

Với điều này, hãy xem xét các mã sau đây.

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;

@interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
@end

@implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
  if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||
    [vTwo rangeOfString:@".."].location != NSNotFound) {
    return SKOrderedNotOrdered;
  }
  NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
  NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
  NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
  if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
    return SKOrderedNotOrdered;
  }
  NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];
  NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];
  for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
    NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
    NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
    if (vOneInt > vTwoInt) {
      return kSKOrderedDescending;
    } else if (vOneInt < vTwoInt) {
      return kSKOrderedAscending;
    }
  }
  if ([vOneArray count] > [vTwoArray count]) {
    for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
      if ([[vOneArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedDescending;
      }
    }
  } else if ([vOneArray count] < [vTwoArray count]) {
    for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
      if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedAscending;
      }
    }
  }
  return kSKOrderedSame;
}
@end

4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Tất nhiên, NSFoundationVersionNumber_iOS_6_1phải thay đổi thành áp dụng cho phiên bản iOS mà bạn muốn kiểm tra. Những gì tôi đã viết bây giờ có thể sẽ được sử dụng rất nhiều khi thử nghiệm nếu một thiết bị đang chạy iOS7 hoặc phiên bản trước đó.


4

đến bữa tiệc muộn một chút nhưng trong phiên bản iOS 8.0 có thể có liên quan:

nếu bạn có thể tránh sử dụng

[[UIDevice currentDevice] systemVersion]

Thay vào đó hãy kiểm tra sự tồn tại của một phương thức / lớp / bất cứ thứ gì khác.

if ([self.yourClassInstance respondsToSelector:@selector(<yourMethod>)]) 
{ 
    //do stuff 
}

Tôi thấy nó hữu ích cho trình quản lý vị trí nơi tôi phải gọi requestWhenInUseAuthorization cho iOS 8.0 nhưng phương thức này không khả dụng cho iOS <8


3
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}

3

Tôi biết đây là một câu hỏi cũ, nhưng ai đó nên đã đề cập đến các macro thời gian biên dịch trong Availability.h. Tất cả các phương thức khác ở đây là các giải pháp thời gian chạy và sẽ không hoạt động trong tệp tiêu đề, danh mục lớp hoặc định nghĩa ivar.

Đối với những tình huống này, sử dụng

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0
  // iOS 6+ code here
#else
  // Pre iOS 6 code here
#endif

h / t câu trả lời này


3
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Sau đó thêm một điều kiện if như sau: -

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
   //Your code
}       

2

Có các phiên bản như 7.0 hoặc 6.0.3, vì vậy chúng ta chỉ cần chuyển đổi phiên bản thành số để so sánh. nếu phiên bản giống như 7.0, chỉ cần thêm một ".0" khác vào đó và sau đó lấy giá trị số của nó.

 int version;
 NSString* iosVersion=[[UIDevice currentDevice] systemVersion];
 NSArray* components=[iosVersion componentsSeparatedByString:@"."];
 if ([components count]==2) {
    iosVersion=[NSString stringWithFormat:@"%@.0",iosVersion];

 }
 iosVersion=[iosVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
 version=[iosVersion integerValue];

Cho 6.0.0

  if (version==600) {
    // Do something
  }

cho 7.0

 if (version==700) {
   // Do something
 }

chỉ cần loại bỏ các dấu thập phân là cách tiếp cận sai. xem xét một thành phần dài hơn 1 ký tự, vd 6.1.10. sau đó thuật toán này sẽ mang lại 6110 > 700, điều này không chính xác.
ardew

Tôi hiểu rằng apple rất tệ trong việc tung ra các phiên bản mới nhưng trong phần lớn thời gian, số thứ hai của phiên bản không bao giờ vượt quá 5, vì vậy 10 là không thể. Đây là một cách tiếp cận adhoc vì vậy nếu nó xử lý trường hợp cho 2 thành phần, bạn có thể sửa đổi nó để xử lý bốn trường hợp aswel nếu bạn muốn làm thủ công. Dù sao, cách tiếp cận này đã được nhận xét tại thời điểm iOS6 hoặc 7. iOS 9 và 10 có nhiều cách tốt hơn để kiểm tra nó, tức là #av Available.
NaXir

2

Hãy thử mã dưới đây:

NSString *versionString = [[UIDevice currentDevice] systemVersion];


1

Là một biến thể của giải pháp yasimturks, tôi đã xác định một hàm và một vài giá trị enum thay vì năm macro. Tôi thấy nó thanh lịch hơn, nhưng đó là vấn đề của hương vị.

Sử dụng:

if (systemVersion(LessThan, @"5.0")) ...

tập tin .h:

typedef enum {
  LessThan,
  LessOrEqual,
  Equal,
  GreaterOrEqual,
  GreaterThan,
  NotEqual
} Comparison;

BOOL systemVersion(Comparison test, NSString* version);

tập tin .m:

BOOL systemVersion(Comparison test, NSString* version) {
  NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
  switch (test) {
    case LessThan:       return result == NSOrderedAscending;
    case LessOrEqual:    return result != NSOrderedDescending;
    case Equal:          return result == NSOrderedSame;
    case GreaterOrEqual: return result != NSOrderedAscending;
    case GreaterThan:    return result == NSOrderedDescending;
    case NotEqual:       return result != NSOrderedSame;
  }
}

Bạn nên thêm tiền tố của ứng dụng vào tên, đặc biệt là Comparisonloại.


1

Sử dụng cách được đề xuất giới thiệu ... nếu không có định nghĩa trong các tệp tiêu đề, bạn luôn có thể nhận được bản in trên bảng điều khiển với một thiết bị của phiên bản IOS mong muốn.

- (BOOL) isIOS8OrAbove{
    float version802 = 1140.109985;
    float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
    NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);
    if (NSFoundationVersionNumber >= version8){
        return true;
    }
    return false;
}

1

Giải pháp kiểm tra phiên bản iOS trong Swift

switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
    case .OrderedAscending:
       println("iOS < 8.0")

    case .OrderedSame, .OrderedDescending:
       println("iOS >= 8.0")
}

Con của giải pháp này: đơn giản là thực hành tồi để kiểm tra số phiên bản hệ điều hành, bất kể bạn làm theo cách nào. Không bao giờ nên phụ thuộc mã cứng theo cách này, luôn luôn kiểm tra các tính năng, khả năng hoặc sự tồn tại của một lớp. Xem xét điều này; Apple có thể phát hành phiên bản tương thích ngược của một lớp, nếu họ đã làm thì mã bạn đề xuất sẽ không bao giờ sử dụng vì logic của bạn tìm số phiên bản HĐH và KHÔNG phải là sự tồn tại của lớp.

( Nguồn thông tin này )

Giải pháp kiểm tra sự tồn tại của lớp trong Swift

if (objc_getClass("UIAlertController") == nil) {
   // iOS 7
} else {
   // iOS 8+
}

Không sử dụng if (NSClassFromString("UIAlertController") == nil)vì nó hoạt động chính xác trên trình giả lập iOS sử dụng iOS 7.1 và 8.2, nhưng nếu bạn thử nghiệm trên thiết bị thực bằng iOS 7.1, bạn sẽ không may nhận thấy rằng bạn sẽ không bao giờ chuyển qua phần khác của đoạn mã.


Tại sao lại bỏ phiếu? Giải pháp này hoạt động hoàn hảo khi sử dụng Swift và bất kỳ phiên bản iOS nào. Đặc biệt là việc kiểm tra sự tồn tại của lớp là hoàn hảo.
King-Wizard

1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)

0

Một phiên bản chung hơn trong Obj-C ++ 11 (bạn có thể thay thế một số nội dung này bằng các hàm NSString / C, nhưng điều này ít dài dòng hơn. Điều này cung cấp cho bạn hai cơ chế. SplitSystemVersion cung cấp cho bạn một loạt các phần hữu ích nếu bạn chỉ muốn bật phiên bản chính (ví dụ switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }).

#include <boost/lexical_cast.hpp>

- (std::vector<int>) splitSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    std::vector<int> versions;
    auto i = version.begin();

    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        versions.push_back(boost::lexical_cast<int>(versionPart));
    }

    return versions;
}

/** Losslessly parse system version into a number
 * @return <0>: the version as a number,
 * @return <1>: how many numeric parts went into the composed number. e.g.
 * X.Y.Z = 3.  You need this to know how to compare again <0>
 */
- (std::tuple<int, int>) parseSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    return {versionAsNumber, nParts};
}


/** Assume that the system version will not go beyond X.Y.Z.W format.
 * @return The version string.
 */
- (int) parseSystemVersionAlt {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end() && nParts < 4) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    // don't forget to pad as systemVersion may have less parts (i.e. X.Y).
    for (; nParts < 4; nParts++) {
        versionAsNumber *= 100;
    }

    return versionAsNumber;
}


0
float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
float versionToBeCompared = 3.1.3; //(For Example in your case)

if(deviceOSVersion < versionToBeCompared)
   //Do whatever you need to do. Device version is lesser than 3.1.3(in your case)
else 
   //Device version should be either equal to the version you specified or above

float versionToBeCompared = 3.1.3;thậm chí không thể biên dịch.
Pang

0

Ví dụ Swift thực sự hoạt động:

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
    println("iOS >= 8.0")
case .OrderedAscending:
    println("iOS < 8.0")
}

Không sử dụng NSProcessInfo vì nó không hoạt động dưới 8.0, vì vậy nó khá vô dụng cho đến năm 2016


0

Đây là một phiên bản nhanh chóng:

struct iOSVersion {
    static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
    static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
    static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
    static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}

Sử dụng:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}

Tôi nghĩ Phiên bản nên là iOSVersion trong dòng 3-6 như struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT < 8.0 && iOSVersion.SYS_VERSION_FLOAT >= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0) }
Kastor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.