Swift를 사용하여 앱 버전과 빌드 번호를 어떻게 얻습니까?


386

Azure 백엔드를 사용하는 IOS 앱이 있고 로그인 및 실행중인 앱 버전과 같은 특정 이벤트를 기록하고 싶습니다.

Swift를 사용하여 버전 및 빌드 번호를 어떻게 반환합니까?



6
스위프트가 아니라 Objective-C입니다.
Øyvind Vik

10
CFBundleVersion& CFBundleShortVersionString`을 혼동하지 마십시오 . 첫 번째는 빌드 버전입니다. 다른 하나는 버전 번호입니다. 자세한 내용은 여기 를 참조 하십시오
Honey

1
@ ØyvindVik 대부분의 사람들은 Objective-C 솔루션을 손으로 잡지 않고 Swift로 번역 할 수 있다고 가정합니다.
gnasher729

답변:


424

편집하다

스위프트 4.2 업데이트

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String

편집하다

새로운 버전의 Xcode에서 @azdev가 지적한 것처럼 이전 솔루션을 시도하는 데 컴파일 오류가 발생합니다.이 문제를 해결하려면!

let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"]

편집 종료

Objective-C에서와 동일한 논리를 사용하지만 약간의 변경이 있습니다.

//First get the nsObject by defining as an optional anyObject
let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary["CFBundleShortVersionString"]

//Then just cast the object as a String, but be careful, you may want to double check for nil
let version = nsObject as! String

이것이 도움이되기를 바랍니다.

데이비드


이것을 사용할 때 컴파일러 오류 "[NSObject : AnyObject]?에"subscript "라는 멤버가 없습니다"
andreas

AnyObject를 교체해 볼 수 있습니까? AnyObject에 의해! 사용중인 코드를 정확히 알지 못하면 잘못된 것을 추측하기가 매우 어렵습니다. 또한 Swift는 한 Xcode 릴리스에서 다른 Xcode 릴리스로 변경할 수 있으므로 Xcode 버전을 아는 것이 중요합니다.
David

18
@andreas infoDictionary는을 사용하여 래핑 해제 해야합니다 !. 이것이 내가 사용하고 Globals.swift 파일에 배치 한 것입니다 :let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String
azdev

1
""를 하나 더 추가해야했습니다. "as"뒤에 let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
yosei

3
강제 랩핑 해제 "!"를 사용하지 않아야합니다. 이러한 값 중 하나가 nil 일 때마다 앱이 다운 될 수 있으므로
Julius

278

나는 이것이 이미 답변되었지만 개인적으로 이것이 조금 더 깨끗하다고 ​​생각합니다.

스위프트 3.0 :

 if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

스위프트 <2.3

if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

이렇게하면 if let 버전이 조건부 처리를 처리하고 (필자의 경우 레이블 텍스트 설정) infoDictionary 또는 CFBundleShortVersionString이 nil 인 경우 선택적 언 래핑으로 인해 코드가 생략됩니다.


6
self.labelVersion.text선택적 유형이므로 직접 할당 할 수 있습니다NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String
Jonauz

8
값이 설정되지 않은 이유가 있습니까? let왜 필요한지 궁금해하는 것에 대해 더 조심스럽게 동의했습니다 . 감사!
Crashalot

@Crashalot은 이름에도 불구하고;) 오타를 만들고 버전 번호가 "뭔가 잘못되었습니다"라고 말하면 앱이 중단되는 것을 원하지 않습니다.
Daniel Springer

OP :? 와 함께! "as String"을 제거하십시오. 그것이 없으면, 어쨌든 충돌하지 않을 것입니다
Daniel Springer

245

스위프트 3.0 업데이트

NS-prefixes 지금 스위프트 3.0에 사라와 몇 가지 특성 / 방법이 더 스위프 티 '로 이름이 변경되었습니다. 다음은 현재 모습입니다.

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
}

Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber

이전 업데이트 된 답변

나는 원래의 대답 이후로 프레임 워크를 많이 사용하여 솔루션을 여러 번들 환경에서 더 간단하고 훨씬 유용한 것으로 업데이트하고 싶었습니다.

extension NSBundle {

    var releaseVersionNumber: String? {
        return self.infoDictionary?["CFBundleShortVersionString"] as? String
    }

    var buildVersionNumber: String? {
        return self.infoDictionary?["CFBundleVersion"] as? String
    }

}

이제이 확장은 앱에서 기본 번들과 포함 된 다른 번들 (확장 프로그래밍을위한 공유 프레임 워크 또는 AFNetworking과 같은 세 번째 프레임 워크)을 모두 식별하는 데 유용합니다.

NSBundle.mainBundle().releaseVersionNumber
NSBundle.mainBundle().buildVersionNumber

// or...

NSBundle(URL: someURL)?.releaseVersionNumber
NSBundle(URL: someURL)?.buildVersionNumber

원래 답변

이미 게시 된 답변 중 일부를 개선하고 싶었습니다. 더 논리적 인 방식으로 처리하기 위해 도구 체인에 추가 할 수있는 클래스 확장을 작성했습니다.

extension NSBundle {

class var applicationVersionNumber: String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]

같이? 문자열 {return version} return "버전 번호를 사용할 수 없음"}

class var applicationBuildNumber: String {
    if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String {
        return build
    }
    return "Build Number Not Available"
}

}

이제 다음을 통해 쉽게 액세스 할 수 있습니다.

let versionNumber = NSBundle.applicationVersionNumber

CFBundleVersionKey는 더 이상 Swift 3, Xcode 8에서 작동하지 않습니다. 사용할 새 키를 알고 있습니까?
Crashalot

71

또한 이것이 이미 답변되었지만 이전 답변을 마무리했습니다.

(*) 확장 프로그램 업데이트

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
    var releaseVersionNumberPretty: String {
        return "v\(releaseVersionNumber ?? "1.0.0")"
    }
}

용법:

someLabel.text = Bundle.main.releaseVersionNumberPretty

@Deprecated : 이전 답변

스위프트 3.1 :

class func getVersion() -> String {
    guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
        return "no version info"
    }
    return version
}

이전 버전의 경우 :

class func getVersion() -> String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
        return version
    }
    return "no version info"
}

레이블 텍스트를 설정하거나 다른 곳에서 사용하려면

self.labelVersion.text = getVersion()

1
또는 : 클래스 func getVersion ()-> 문자열 {return NSBundle.mainBundle (). infoDictionary? [ "CFBundleShortVersionString"] as? 문자열 ?? "버전 정보 없음"}
tapmonkey

다른 답변을 복사하는 것이 의미가 없다고 생각합니다. 귀하의 답변이 더 이상 유효하지 않은 경우 언제든지 삭제할 수 있으며 다른 답변을위한 공간을 확보하십시오.)
carmen_munich

1
@carmen_munich 여기에 중상 모략 이니 답을 드리겠습니다 우선,이 답변은 2015 년 3 월에 게시되고 귀하의 답변은 2017 년 2 월에 게시됩니다. 따라서 영감은 이전 답변에서 나왔어야합니다. 둘째, 나는 당신의 대답을 전혀 보지 못했습니다. 요즘 나는이 방법을 사용하기 때문에 대답을 업데이트했습니다. 확장 기능을 사용하는 것은 iOS 커뮤니티의 누군가에게 고유하지 않습니다. 정말 성숙하고 다른 개발자를 존중하십시오. 여기에 게시하는 내용이 없습니다. 나는 사람들에게 도움을주고 싶습니다. SO를 돕고 자하는 사람들을 낙담시키지 마십시오.
Gunhan

나는 초보자로부터 답변을 게시하고 사람들이 "위"를 클릭하여 사람들을보고 동기를 부여하는 것을보고 싶다는 의견을 많이 들었습니다. 그러나 누군가가 오래된 답변에 답변을 복사하면 게시하려는 노력을 기울인 사람은 누군가가 투표 한 동기를 얻지 못할 것입니다. 따라서 초보자들은 실제로 실망감을 느끼고 커뮤니티에 가치를 가져다주지 않으며 게시를 중단한다고 생각합니다. 그리고 잘못 이해하지 마십시오. 나는 이것을 일반적으로 의미합니다. 내가이 제안을 한 이유를 기분 나쁘게 느끼고 더 잘 이해하기를 바랍니다.
carmen_munich

@carmen_munich이 질문에 대한 답변을 시간순으로 주문하면 다른 사람이 이전과 똑같은 답변을 이미 받았음을 알 수 있습니다! 그래서 당신은 당신이 한 일을 저를 탓하고 있습니다. 이 질문에 대한 이력이 있으므로 업데이트에서 새로운 사용 환경 설정을 공유했습니다. 그게 다야.
Gunhan

32

대한 스위프트 4.0

let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!

28

번들에 확장 프로그램을 만들었습니다

extension Bundle {

    var appName: String {
        return infoDictionary?["CFBundleName"] as! String
    }

    var bundleId: String {
        return bundleIdentifier!
    }

    var versionNumber: String {
        return infoDictionary?["CFBundleShortVersionString"] as! String 
    }

    var buildNumber: String {
        return infoDictionary?["CFBundleVersion"] as! String
    }

}

그런 다음 사용하십시오

versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"

실제로는 조금 다릅니다. 예를 들어 강제 언 래핑을 사용합니다. 당신은 일반적으로 힘을 풀어주는 것이 좋지 않다고 생각할 수도 있습니다. 이것은 드문 경우이지만 괜찮습니다. 좀 더 설명하기 위해 이러한 값은 사전에 있어야합니다. 그렇지 않으면 프로젝트 파일에 실제로 잘못된 것이 있습니다. 왜이 방법이 :-) 풀기 힘 사용의 그
carmen_munich

이름을 바꾸고 강제로 풀기 작업을 새 답변으로 게시하는 것은 아닙니다. 또한 사람들은 답을 볼 수있는 곳이면 어디에서나 강제로 풀기 기능을 사용할 수 있다는 것을 알게 될 것입니다. 독자에게는 키가 있다고 가정하지 말고 강제 래핑 해제보다는 수동으로 래핑 해제 옵션을 처리하는 것이 좋습니다.
Gunhan

공정하게하기 위해 강제 언 랩핑이 좋은 드문 경우가 있습니다. 이 게시물은 괜찮을 수있는 경우를 보여줍니다. 강제 언 래핑 사례에 대해 더 알고 싶다면 Paul Hudson의 좋은 설명과 자습서가 있습니다. 난 정말 모든 초보자에게 추천 할 수 있습니다 www.hackingwithswift.com
carmen_munich

초보자에게는 좋은 추천입니다. 더 많은 것을 읽고 더 배울 수도 있습니다. 또한 의견과 그 의미에 대한 이해를 향상시켜야합니다. 예를 들어, 아무도 당신에게 절대로 언 래핑을 사용하지 말라고 말하지 않았습니다. 그러나 정보에 따르면 이러한 키를 제거하고 강제로 풀면 충돌이 발생할 수 있습니다. 포장 풀기를 처리하는 것이 더 안전합니다.
Gunhan

어쩌면 어떤 경우에 그들이 제거되고 무질서한지 설명 할 수 있습니까? 내가 언급 한 자료에서 배운 것은이 partiuclare 사례가 아닙니다. 프로젝트 파일이 손상되지 않는 한 항상 있어야합니다.이 경우 프로젝트는 어쨌든 컴파일되지 않을 것입니다.
carmen_munich

16

Swift 3.0 NSBundle이 작동하지 않으면 다음 코드가 완벽하게 작동합니다.

let versionNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
          as! String

빌드 번호의 경우 다음과 같습니다.

let buildNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
          as! String

혼란스럽게도 'CFBundleVersion'은 일반 -> ID의 Xcode에 입력 된 빌드 번호입니다.


15

Xcode 9.4.1 스위프트 4.1

localizedInfoDictionary를 사용하여 올바른 언어 버전의 번들 표시 이름을 선택하십시오.

var displayName: String?
var version: String?
var build: String?

override func viewDidLoad() {
    super.viewDidLoad()

    // Get display name, version and build

    if let displayName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String {
        self.displayName = displayName
    }
    if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
        self.version = version
    }
    if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
        self.build = build
    }
}

14

Xcode 8, 스위프트 3 :

let gAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let gAppBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"

12

스위프트 4, 번들을위한 유용한 확장

import Foundation

public extension Bundle {

    public var shortVersion: String {
        if let result = infoDictionary?["CFBundleShortVersionString"] as? String {
            return result
        } else {
            assert(false)
            return ""
        }
    }

    public var buildVersion: String {
        if let result = infoDictionary?["CFBundleVersion"] as? String {
            return result
        } else {
            assert(false)
            return ""
        }
    }

    public var fullVersion: String {
        return "\(shortVersion)(\(buildVersion))"
    }
}

이것을 사용하려면 Bundle.main.fullVersion과 같은 말이 필요합니다
Joseph Astrahan

11

번들 + 확장명 .swift

import Foundation

extension Bundle {
    var versionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }

    var buildNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }

    var bundleName: String? {
        return infoDictionary?["CFBundleName"] as? String
    }
}

용법:

someLabel.text = Bundle.main.versionNumber

11

OP는 버전 번호와 빌드 번호를 모두 요청했습니다. 불행히도 대부분의 답변은 이러한 옵션을 모두 제공하지는 않습니다. 또한 불필요한 확장 방법을 추가하는 것도 있습니다. 다음은 매우 간단하고 OP의 문제를 해결하는 것입니다.

// Example output: "1.0 (234)"
private func versionAndBuildNumber() -> String {
  let versionNumber = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
  let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
  if let versionNumber = versionNumber, let buildNumber = buildNumber {
    return "\(versionNumber) (\(buildNumber))"
  } else if let versionNumber = versionNumber {
    return versionNumber
  } else if let buildNumber = buildNumber {
    return buildNumber
  } else {
    return ""
  }
}

9

Swift가 계속 진화하고 있음을 감안할 때 (2015 년 8 월 현재) 내 대답 :

let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

8

UIApplication에 대한 확장을 만들었습니다.

extension UIApplication {
    static var appVersion: String {
        let versionNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.versionNumber] as? String
        let buildNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.buildNumber] as? String

        let formattedBuildNumber = buildNumber.map {
            return "(\($0))"
        }

        return [versionNumber,formattedBuildNumber].compactMap { $0 }.joined(separator: " ")
    }
}

struct IdentifierConstants {
    struct InfoPlist {
        static let versionNumber = "CFBundleShortVersionString"
        static let buildNumber = "CFBundleVersion"
    }
}

6

설명서를 살펴본 결과 다음이 더 깨끗하다고 ​​생각합니다.

let version = 
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") 
as? String

출처 : "사용할 수있는 키의 현지화 된 값을 반환하기 때문에이 방법을 사용하는 것이 다른 액세스 방법보다 선호됩니다."



5

Swift 1.2의 경우 다음과 같습니다.

let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

1
당신은 사용할 수 있습니까? 또한
Dan Rosenstark

4

스위프트 3 :

버전 번호

if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }

빌드 번호

if let buildNumberString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { // do something }

빌드 번호는 어떻습니까? 감사! CFBundleVersionKey가 작동하지 않습니다.
Crashalot

@Crashalot 빌드 번호로 업데이트했습니다. 여기에 모든 핵심 재단 키의 목록도있다 : developer.apple.com/library/content/documentation/General/...은
jasonnoahchoi

3

스위프트 4

func getAppVersion() -> String {
    return "\(Bundle.main.infoDictionary!["CFBundleShortVersionString"] ?? "")"
}

Bundle.main.infoDictionary! [ "CFBundleShortVersionString"]

신속한 이전 구문

let appVer: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]

2
extension UIApplication {

    static var appVersion: String {
        if let appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") {
            return "\(appVersion)"
        } else {
            return ""
        }
    }

    static var build: String {
        if let buildVersion = NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) {
            return "\(buildVersion)"
        } else {
            return ""
        }
    }

    static var versionBuild: String {
        let version = UIApplication.appVersion
        let build = UIApplication.build

        var versionAndBuild = "v\(version)"

        if version != build {
            versionAndBuild = "v\(version)(\(build))"
        }

        return versionAndBuild
    }

}

주의 : 앱 버전이나 빌드가 설정되어 있지 않으면 사용하려고하면 충돌이 발생할 수 있습니다! 풀다.


2

Swift 3.2의 업데이트 버전은 다음과 같습니다.

extension UIApplication
{
    static var appVersion:String
    {
        if let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
        {
            return "\(appVersion)"
        }
        return ""
    }

    static var buildNumber:String
    {
        if let buildNum = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String)
        {
            return "\(buildNum)"
        }
        return ""
    }

    static var versionString:String
    {
        return "\(appVersion).\(buildNumber)"
    }
}

2

이전과 같이 문자열 형식의 코드를 사용하지 않고 상수를 사용할 수 있으므로 훨씬 편리합니다.

var appVersion: String {
    return Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String
}

2
public var appVersionNumberString: String {
    get {
        return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
    }
}

1

스위프트 4

// 선택적 AnyObject로 정의하여 먼저 nsObject를 가져옵니다.

let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject

// 그냥 객체를 String으로 캐스팅하지만 nil을 다시 확인해야 할 수도 있습니다.

let version = nsObject as! String

1

앱 버전을 Int 로 반환하는 간단한 유틸리티 기능

func getAppVersion() -> Int {

        if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {

            let appVersionClean = appVersion.replacingOccurrences(of: ".", with: "", options: NSString.CompareOptions.literal, range:nil)

            if let appVersionNum = Int(appVersionClean) {
                return appVersionNum
            }
        }
        return 0
    }

1
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
            self.lblAppVersionValue.text = version
        }

0

관심있는 사람이라면 누구나 githubSwifterSwift 에서 사용할 수 있는 멋지고 깔끔한 라이브러리가 있으며 모든 버전의 swift 버전에 대해 완벽하게 문서화되어 있습니다 ( swifterswift.com 참조 ).

이 라이브러리를 사용하면 앱 버전과 빌드 번호를 읽는 것이 다음과 같이 쉽습니다.

import SwifterSwift

let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion

0
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
        lblVersion.text = "Version \(version)"

    }

0

스위프트 5 업데이트

다음은 "앱 업데이트"페이지를 표시할지 여부를 결정하는 데 사용하는 기능입니다. 빌드 번호를 반환합니다.이 숫자는 Int로 변환 중입니다.

if let version: String = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
        guard let intVersion = Int(version) else { return }

        if UserDefaults.standard.integer(forKey: "lastVersion") < intVersion {
            print("need to show popup")
        } else {
            print("Don't need to show popup")
        }

        UserDefaults.standard.set(intVersion, forKey: "lastVersion")
    }

전에 사용하지 않으면 현재 빌드 번호보다 낮은 0을 반환합니다. 새로운 사용자에게 이러한 화면을 표시하지 않으려면 첫 번째 로그인 후 또는 온 보딩이 완료된 후 빌드 번호를 추가하십시오.


0

대한 스위프트 5.0 :

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String

0

UIApplication 확장으로서의 Swift 5

extension UIApplication {
    static var release: String {
        return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String? ?? "x.x"
    }
    static var build: String {
        return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String? ?? "x"
    }
    static var version: String {
        return "\(release).\(build)"
    }
}

사용 예 :

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