Swift에서 OS 버전을 확인 하시겠습니까?


191

Swift에서 시스템 정보를 확인하려고합니다. 코드로 달성 할 수 있다고 생각했습니다.

var sysData:CMutablePointer<utsname> = nil
let retVal:CInt = uname(sysData)

이 코드에는 두 가지 문제가 있습니다.

  1. sysData의 초기 값은 무엇입니까? 이 예는 아마도 sysData가 nil이기 때문에 retVal에서 -1을 제공합니다.
  2. sysData에서 정보를 어떻게 읽을 수 있습니까?

답변:


388

iOS의 경우 다음을 시도하십시오.

var systemVersion = UIDevice.current.systemVersion

OS X의 경우 다음을 시도하십시오.

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

사용자가 최소한 특정 버전을 실행하고 있는지 확인하려는 경우 iOS 및 OS X에서 작동하는 다음 Swift 2 기능을 사용할 수도 있습니다.

if #available(iOS 9.0, *) {
    // use the feature only available in iOS 9
    // for ex. UIStackView
} else {
    // or use some work around
}

그러나 OS 버전을 확인하지 않는 것이 좋습니다. 사용하려는 기능이 버전 번호를 비교하는 것보다 장치에서 사용 가능한지 확인하는 것이 좋습니다. 위에서 언급 한대로 iOS의 경우 선택기에 응답하는지 확인해야합니다. 예 :

if (self.respondsToSelector(Selector("showViewController"))) {
    self.showViewController(vc, sender: self)
} else {
    // some work around
}

이것은 객관적인 c에 맞지만 신속하게 처리하는 훨씬 좋은 방법이 있습니다. 여기에 설명되어 있습니다 ... hackingwithswift.com/new-syntax-swift-2-availability-checking
Fogmeister

2
특정 기능을 확인하는 대신 OS 버전을 직접 확인하는 한 가지 용도는 사용자 간의 OS 버전 배포에 대한 데이터를 수집하여 가장 낮은 배포 대상을 결정하는 것입니다.
Nicolas Miari

91

업데이트 :
이제 Swift 2에 도입 된 새로운 가용성 검사 를 사용해야합니다 .
예 : 컴파일 타임 에 iOS 9.0 이상을 확인하려면 다음을 사용하십시오.

if #available(iOS 9.0, *) {
    // use UIStackView
} else {
    // show sad face emoji
}

또는 전체 방법이나 클래스와 함께 사용할 수 있습니다

@available(iOS 9.0, *)
func useStackView() {
    // use UIStackView
}

자세한 내용은 이것을 참조 하십시오 .

런타임 점검 :

정확한 버전을 원하지 않지만 다음을 사용하여 iOS 9,10 또는 11을 확인하려는 경우 :

let floatVersion = (UIDevice.current.systemVersion as NSString).floatValue

편집 : 방금 이것을 달성하는 다른 방법을 찾았습니다.

let iOS8 = floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1)
let iOS7 = floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_7_1)

50

아래 링크에서 신속하게 전달 된 도우미 기능을 만들었습니다.

장치에서 실행중인 iOS 버전을 프로그래밍 방식으로 감지하려면 어떻게해야합니까?

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}

다음과 같이 사용할 수 있습니다.

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

스위프트 4.2

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == .orderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == .orderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != .orderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == .orderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != .orderedDescending
}

31

스위프트 5

ProcessInfo버전 정보를 제공 하므로 확장 프로그램을 만들 필요가 없습니다 . 아래와 같이 iOS 용 샘플 코드를 볼 수 있습니다.

let os = ProcessInfo().operatingSystemVersion

switch (os.majorVersion, os.minorVersion, os.patchVersion) {
case (let x, _, _) where x < 8:
    print("iOS < 8.0.0"

case (8, 0, _):
    print("iOS >= 8.0.0, < 8.1.0")

case (8, _, _):
    print("iOS >= 8.1.0, < 9.0")

case (9, _, _):
    print("iOS >= 9.0.0")

default:
    print("iOS >= 10.0.0")
}

참조 : http://nshipster.com/swift-system-version-checking/


17

스위프트 5

func run() {
    let version = OperatingSystemVersion(majorVersion: 13, minorVersion: 0, patchVersion: 0)
    if ProcessInfo.processInfo.isOperatingSystemAtLeast(version) {
        runNewCode()
    } else {
        runLegacyCode()
    }
}

func runNewCode() {
    guard #available(iOS 13.0, *) else {
        fatalError()
    }
    // do new stuff
}

func runLegacyCode() {
    // do old stuff
}

1
runNewCode에서 #available (iOS 11.0, *)이 필요한 이유는 무엇입니까?
Illya Krit

1
@IllyaKrit이 #available(...)블록은 컴파일러가 제공된 것보다 오래된 버전에서 지원되지 않는 코드에 대한 오류를 표시하지 않도록합니다.
미래

15

이 싱글 톤을 간단하게 사용 하고 IOSVersion.swift파일을 만들고이 코드를 추가했습니다.

import UIKit

public class IOSVersion {
    class func SYSTEM_VERSION_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
    }

    class func SYSTEM_VERSION_GREATER_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
    }

    class func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
    }
}

사용하다 :

IOSVersion.SYSTEM_VERSION_EQUAL_TO("8.0")
IOSVersion.SYSTEM_VERSION_LESS_THAN("8.0")

감사합니다 @KVISH

스위프트 2 편집 :

if #available(iOS 9.0, *) {
    // 👍 
} else {
    // 👎
}

4
싱글 톤인가요? 또는 IOSVersion의 클래스 함수입니까? 싱글은되지 않을 것 static let shared = IOSVersion
찰튼 Provatas

9

Swift 2를 사용 중이고 특정 API를 사용하도록 OS 버전을 확인하려는 경우 새로운 가용성 기능을 사용할 수 있습니다.

if #available(iOS 8, *) {
    //iOS 8+ code here.
}
else {
    //Code for iOS 7 and older versions.
    //An important note: if you use #availability, Xcode will also 
    //check that you don't use anything that was introduced in iOS 8+
    //inside this `else` block. So, if you try to use UIAlertController
    //here, for instance, it won't compile. And it's great.
}

이 답변은 Google에서 swift 2 check system version쿼리에 대한 첫 번째 질문이므로이 답변을 작성했습니다 .


7

Swift 3.0 이상 업데이트

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedDescending
}

1
ComparisonResult더 짧게 건너 뛸 수 있습니다.
John Pang

또한 코드 UIDevice.current.systemVersion.compare(version, options: .numeric)를 고려 하면 func코드를 읽는 데 도움이됩니다.
John Pang

5

세부

  • Xcode 10.2.1 (10E1001), 스위프트 5

연결

운영 체제 버전

해결책

extension OperatingSystemVersion {
    func getFullVersion(separator: String = ".") -> String {
        return "\(majorVersion)\(separator)\(minorVersion)\(separator)\(patchVersion)"
    }
}

let os = ProcessInfo().operatingSystemVersion
print(os.majorVersion)          // 12
print(os.minorVersion)          // 2
print(os.patchVersion)          // 0
print(os.getFullVersion())      // 12.2.0

1
사용하는 경우 잠재적 인 반올림 문제가되지 있는가 Double예를 들어, 버전 번호 10.0999대신 10.1?
mschmidt

아니요 var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999, 인쇄됩니다10.0999
Vasily Bodnarchuk

4
let Device = UIDevice.currentDevice()
let iosVersion = NSString(string: Device.systemVersion).doubleValue

let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8

로 확인

if(iOS8)
{

}
else 
{
}  

4

Swift 2 이상에서 시스템 버전 및 기타 여러 버전을 확인하는 가장 쉽고 간단한 방법은 다음과 같습니다.

if #available(iOS 9.0, *) { // check for iOS 9.0 and later

}

또한 #available다음 버전을 확인할 수 있습니다.

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson은 매우 편리한 방법을 공유합니다

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

2

스위프트 4.x

func iOS_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedSame
}

func iOS_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending
}

func iOS_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: NSString.CompareOptions.numeric) != ComparisonResult.orderedAscending
}

func iOS_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
}

func iOS_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: NSString.CompareOptions.numeric) != ComparisonResult.orderedDescending
}

용법:

if iOS_VERSION_GREATER_THAN_OR_EQUAL_TO(version: "11.0") {
    //Do something!
}

PS KVISH 답변은 iOS 앱 에이 스 니펫을 사용하고 있으므로 기능의 이름을 바꾸어 Swift 4.x로 번역했습니다.


1

참고 : iOS 8.0 이상에서 사용 가능합니다. OS X v10.10 이상

var majorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.majorVersion }
var minorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.minorVersion }
var patchVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.patchVersion }
var myOSVersion:  String { return NSProcessInfo.processInfo().operatingSystemVersionString        }

1

Matt Thompson의 답변을 바탕으로 iOS 7 이상 에서 SwiftObjective-c 와 함께 작동하는 개별 단위 테스트가있는 방법이 있습니다 ( 더 이상 NSFoundationNumber 를 확인할 수없는 iOS 9 포함 ).

+ (BOOL) isAtLeastOSVersion:(NSString *)osVersion
{
    switch ([[UIDevice currentDevice].systemVersion compare:osVersion options:NSNumericSearch]) {
        case NSOrderedSame:
        case NSOrderedDescending:
            return YES;
        default:
            return NO;
    }
}  

.

@interface ANFakeCurrDevice : NSObject
@property (nonatomic, strong) NSString *systemVersion;
@end
@implementation ANFakeCurrDevice
@end


@implementation MyHelperClassUnitTests

- (void)setUp {
    [super setUp];
}

- (void)tearDown {
    [super tearDown];
}

- (void)test_isAtLeastOSVersion
{
    id deviceMock = [OCMockObject niceMockForClass:[UIDevice class]];
    ANFakeCurrDevice *fakeCurrDevice = [ANFakeCurrDevice new];
    fakeCurrDevice.systemVersion = @"99.9.9";
    [[[deviceMock stub] andReturn:fakeCurrDevice] currentDevice];
    XCTAssertTrue([[UIDevice currentDevice].systemVersion isEqualToString:@"99.9.9"]);

    fakeCurrDevice.systemVersion = @"1.0.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.0.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.1.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.1.0"]);


    fakeCurrDevice.systemVersion = @"8.4.0";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"7.0.1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.2"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);

    fakeCurrDevice.systemVersion = @"8.4.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);
}


@end

당신은 실제 방법이 매우 짧고 간결하다는 것을 알고 있습니다. 방금 예시와 작동을위한 단위 테스트 코드를 추가했습니다.
n8tr

XCTest라는 것을 한 눈에 알지 못해서 죄송합니다.
DawnSong

1
let osVersion = NSProcessInfo.processInfo().operatingSystemVersion
let versionString = osVersion.majorVersion.description + "." + osVersion.minorVersion.description + "." + osVersion.patchVersion.description
print(versionString)

0

또한 WatchOS를 확인하려는 경우.

빠른

let watchOSVersion = WKInterfaceDevice.currentDevice().systemVersion
print("WatchOS version: \(watchOSVersion)")

목표 -C

NSString *watchOSVersion = [[WKInterfaceDevice currentDevice] systemVersion];
NSLog(@"WatchOS version: %@", watchOSVersion);

0

시스템의 현재 버전을 가져 와서 분할하십시오. 따라서 메이저 버전과 마이너 버전을 얻을 수 있습니다.

let sys_version = UIDevice.current.systemVersion
let all_version = sys_version.components(separatedBy: ".")
print("Major version : \(all_version[0])")
print("Minor version : \(all_version[1])")

0

여기에 작성된 대부분의 샘플 코드는 0이 아닌 버전에서 예기치 않은 결과를 얻습니다. 예를 들어

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedAscending
}

이 메소드는 iOS "10.3"에서 전달 된 버전 "10.3.0"에서는 true를 반환하지 않습니다. 이러한 종류의 결과는 의미가 없으며 동일한 버전으로 간주해야합니다. 정확한 비교 결과를 얻으려면 버전 문자열에서 모든 숫자 구성 요소를 비교하는 것을 고려해야합니다. 또한 모든 대문자로 글로벌 메소드를 제공하는 것은 좋은 방법이 아닙니다. SDK에서 사용하는 버전 유형이 문자열이므로 문자열에서 비교 기능을 확장하는 것이 좋습니다.

시스템 버전을 비교하려면 다음 예제가 모두 작동해야합니다.

XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThan: "99.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(equalTo: UIDevice.current.systemVersion))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThan: "3.5.99"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThanOrEqualTo: "10.3.0.0.0.0.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThanOrEqualTo: "10.3"))

내 저장소에서 확인할 수 있습니다 https://github.com/DragonCherry/VersionCompare

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.