ChatGPT解决这个技术问题 Extra ChatGPT

What values should I use for CFBundleVersion and CFBundleShortVersionString?

ios

This is my first iOS app submission and I don't want my app rejected.

This is from the Apple Docs:

CFBundleVersion (String - iOS, OS X) specifies the build version number of the bundle, which identifies an iteration (released or unreleased) of the bundle. The build version number should be a string comprised of three non-negative, period-separated integers with the first integer being greater than zero. The string should only contain numeric (0-9) and period (.) characters. Leading zeros are truncated from each integer and will be ignored (that is, 1.02.3 is equivalent to 1.2.3). This key is not localizable.

CFBundleShortVersionString (String - iOS, OS X) specifies the release version number of the bundle, which identifies a released iteration of the app. The release version number is a string comprised of three period-separated integers. The first integer represents major revisions to the app, such as revisions that implement new features or major changes. The second integer denotes revisions that implement less prominent features. The third integer represents maintenance releases.

The value for this key differs from the value for “CFBundleVersion,” which identifies an iteration (released or unreleased) of the app. This key can be localized by including it in your InfoPlist.strings files.

But it seems a bit strange. My interpretation for this is to put both values the same, i.e.:

CFBundleVersion: 1.0.0
CFBundleShortVersionString: 1.0.0

Can someone confirm 100% that is what I am supposed to put?

According to that, CFBundleShortVersionString can be localized. But if it has to be three integers separated by periods, what localization is possible?
@Rick I suppose that means you can convert it for languages that actually have different numerals, like Arabic?
@shiser Just to be pedantic, "arabic numerals" are actually the numerals that we use in the western world, and most other places too. But I get what you mean, and there are some parts of the arabic world that don't use "arabic numerals". en.wikipedia.org/wiki/Arabic_numerals
Another answer in here. stackoverflow.com/q/21125159/419348

Y
Yunus Nedim Mehel

CFBundleShortVersionString gives you the version of your app. It's typically incremented each time you publish your app to the App Store. This is the version that is visible on the "Version" section for the App Store page of your application.

CFBundleVersion gives you the build number which is used for development and testing, namely "technical" purposes. The end user is rarely interested in the build number but during the development you may need to know what's being developed and fixed on each build. This is typically incremented on each iteration of internal release. And you can use continuous integration tools like Jenkins to auto-increment the build number on each build.

https://i.stack.imgur.com/HNrrs.jpg

The two numbers do not depend on each other but it is a good idea to keep them parallel to avoid confusion. Keep in mind that once your app has passed the App Store review you need to increment the build number like Phil and likeTheSky have stated, regardless of whether you publish it or not.

Use case: Let's say, you have a well-tested build, ready for submission. It's version number is 1.0.0 and build number is 1.0.0.32. Once you submit your app, you need to update the version as 1.0.1 and build number as 1.0.1.0.


So, is it safe to ignore that bit in the docs (quoted in the question) about CFBundleVersion being "three" period-separated values?
I think its up to you. If you do not publish a release frequently or if you do not need to strictly follow bug fixes through frequent test cycles; you might as well use 3 digits for both of them.
so can CFBundleVersion be 0 for an app store build? Will Apple reject it?
Yes, you can use values other than 3 numbers with punctuation. I have used a date-time value such as 201606070620 in a shipping iOS app.
@BasilBourque, if you don't follow guidelines, you may run into a problem if you use in-app purchases. See Technical Note 2413
r
rmaddy

Think of it this way: The "short version" (CFBundleShortVersionString) is the public version number. The "version" (CFBundleVersion) is more of an internal version number that could change far more frequently than the public "short version". Personally I use the same for both but many people update the "version" on every build. Either way you typically update the "short version" when you release to Apple. How often you update the "version" is up to you and your needs.


Be aware that the bundle version (CFBundleVersion) must numerically exceed the bundle version of your previous app or it will get an error when submitting to the App Store. See stackoverflow.com/questions/4933093/….
Similar to what Phil says above, nowadays, if you resubmit a failed (not approved by App Store) build, it looks like you need to bump the CFBundleVersion on each submission now, so likely these numbers will diverge unless you're always perfect, or you don't mind bumping your public (CFBundleShortVersionString) version # upon any change needed for successful submission to App Store.
C
Community

The answer by rmaddy is correct. I'll add two more thoughts.

Third Version Number

Be aware of the third version number, specified on the iTunesConnect web site as part of your app's definition. If that number is different than the two in Xcode, Apple gives you a warning. You can ignore the warning, as it is not a show-stopper (not an "error").

Date-Time as version

Also, you need not use three numbers with punctuation. That may may sense for some apps, where traditionally changes in the first number indicated some kind of dramatic change usually affecting compatibility.

For other apps you might want to use simply a date-time value in ISO 8601 standard format style (YYYYMMDDHHMM). For example, 201606070620. That order of year-month-date-hour-minute renders an ever-increasing number, always the same length due to padding zero, that when sorted alphabetically is also chronological.

I have successfully used this style of version numbers on a shipping iOS app working in iOS 7, 8, & 9.

You can even automate the generation of this value. In your project’s Target > Build Phases > Run Script panel:

Specify in the Shell field: /bin/sh Paste the following 5 line script seen below. (optional) Check the Show environment variables in build log checkbox. Uncheck the Run script only when installing checkbox.

Every time you do a build the current date-time in UTC time zone is captured. The -u flag in the script makes use of UTC rather than your current default time zone. Generally best for programmers and sysadmins to be using and thinking in UTC rather than local time zones.

#!/bin/bash
buildNumber=$(date -u "+%Y%m%d%H%M")
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildNumber" "$INFOPLIST_FILE"  # Version number
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"  # Build number
echo "DateTime for app version number: $buildNumber"

Or do a hybrid, with a conventional 1.2.3 for the Version number and a date-time as the Build number. To do the hybrid, simply comment-out the CFBundleShortVersionString line with a # in front.


p
plindberg

The scheme most sensible to me is to use the version number (ie. CFBundleShortVersionString) for the actual version number, and then use the build number (ie. CFBundleVersion) to represent the submission to the App Store. So unless there are any problems and hence re-submits, this number is always 1. For a new release, I reset to 1 if the previous had issues in TestFlight testing or in review.

Build numbers provide a way to name each of the submissions you provide for a particular release. As described in the definitions above, the collection of all of the builds that you provide for a particular version of your app is called that version's 'release train'. For iOS apps, build numbers must be unique within each release train, but they do not need to be unique across different release trains [my emphasis]. That is to say, for iOS Apps you can use the same build numbers again in different release trains if you want to.

From Technical Note TN2420: Version Numbers and Build Numbers.


Good to see an answer that provides an official reference confirming the interpretations presented in other answers on this page.
Q
Qiulang

I use CFBundleVersion to indicate internal build for CFBundleShortVersionString. I use test flight to submit builds for my testers so the difference between them has been extremely useful.

Apple documents says CFBundleVersion "should be a string comprised of 3 non-negative, period-separated integers" But actually it can be MORE THAN 3 parts(as the above answer shows). I use that to indicate my development build, say my CFBundleShortVersionString is 1.0.0, I can use 1.0.0.11 for CFBundleVersion to indicate that is my 11th build for release 1.0.0

Each CFBundleVersion submitted to app store should be bigger than before or you will get ERROR ITMS-90478: "Invalid Version. The build with the version “xxx” can’t be imported because a later version has been closed for new build submissions. Choose a different version number."

CFBundleShortVersionString can only have 3 parts or you will get ERROR ITMS-90060:The value for key CFBundleShortVersionString 'xxx' in the Info.plist file must be a period-separated list of at most three non-negative integers."

The 3rd number that Basil Bourque mentioned, i.e. the version number shows on iTunesConnect is where things may get complicated.

I use a different iTunesConnect number than CFBundleShortVersionString because when I first submitted my app to app store we already have many rounds of internal releases. So I used 1.0 for iTunesConnect number and 5.x for CFBundleShortVersionString. In the next release to app store I provided a function to check if there is a newer version in the app store and realized I had trouble now because I can only get iTunesConnect number (using http://itunes.apple.com/lookup?bundleId=) so I need to do some calculation to before compare it with CFBundleShortVersionString number.

I tried to fix that by using iTunesConnect number as my CFBundleShortVersionString, but got the error, ERROR ITMS-90062: "This bundle is invalid. The value for key CFBundleShortVersionString [x.x.x] in the Info.plist file must contain a higher version than that of the previously approved version [x.x.x]."

So I will suggest always make them the same.


K
Kenny Evitt

As-of now, the Apple documentation for CFBundleVersion states [emphasis mine]:

The build version that identifies an iteration of the bundle. ... This key is a machine-readable string composed of one to three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods. ... You can include more integers but the system ignores them.

For CFBundleShortVersionString [emphasis mine]:

The release or version number of the bundle. ... This key is a user-visible string for the version of the bundle. The required format is three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods.

I'd suggest just automatically incrementing CFBundleVersion for each build (or every release to TestFlight) and resetting it to 0 whenever you change CFBundleShortVersionString.

You should explicitly plan, or devise a consistent means, to update the user visible version in CFBundleShortVersionString.


Thank you for an answer referring to the latest Apple documentation. I would give rep to upvote this more than once.
D
Dave Evans

Something I've never seen discussed anywhere is what is the maximum number for each field in a CFBundleVersion?

By setting CFBundleVersion in a app to 1.1.1 and looking at the hexadecimal vaue for the version in "lsregister -dump", I determined that the maximum value for the first field is (2^22)-1 or 4194303, and the maximum values for the second and third fields are (2^21)-1 or 2097151.

The 3 fields add up to 64 bits.

This has implications for those of us who use CFBundleVersion based on date and time.

I was setting the first field to YYYYMMDD. This is always greater than the max allowed versions and it was leading to unpredictable results, to say the least, when Launch Services was deciding which version of an app to run when you had multiple versions installed and were using something like 'open -a Appname' from the command line.

Please spread this widely. I am sure a lot of people are coming unstuck with this.


Do you recall what is done if a fourth field is added (1.1.1.20191201) and what you end up using instead? I really wish Apple just used the same numeric value that android did here. P.S. thanks for looking this up!
I believe the restriction is documented here and is quite a bit more restrictive than what is mentioned here.