Use same CFBundleVersion and CFBundleShortVersionS

2020-02-28 02:29发布

问题:

I received the following email from Apple when I submit an app update:

We have discovered one or more issues with your recent delivery for "Project". Your delivery was successful, but you may wish to correct the following issues in your next delivery:

CFBundleVersion Mismatch - The CFBundleVersion value '1' of extension 'Project.app/PlugIns/ProjectTodayExtension.appex' does not match the CFBundleVersion value '985' of its containing iOS application 'Project.app'.

CFBundleShortVersionString Mismatch - The CFBundleShortVersionString value '1.0' of extension 'Project.app/PlugIns/ProjectTodayExtension.appex' does not match the CFBundleShortVersionString value '2.1.6' of its containing iOS application 'Project.app'.

After you’ve corrected the issues, you can use Xcode or Application Loader to upload a new binary to iTunes Connect.

Is there any way of use the same CFBundleVersion and CFBundleShortVersionString in all targets to prevent this?

回答1:

My solution is:

For CFBundleShortVersionString:

  • Add a user-defined constant in your project settings

  • Name it $(CF_BUNDLE_SHORT_VERSION_STRING) and set it to your desired value

  • Set your version in your targets to $(CF_BUNDLE_SHORT_VERSION_STRING)

  • Repeat for all targets. Done!

CFBundleVersion: you could do the same for CFBundleVersion, but somehow I wanted this value to be computed from my GIT repo commit count. I´ve done it like this:

  • Add a Pre-action to your main target. You access the shown dialog via Product > Scheme > Edit Scheme

  • Add a Post-action to your main target.

  • Add a new Command Line Tool target named BundleVersionUpdate and one named BundleVersionRevert

  • Navigate to your new BundleVersionUpdate target and add a new Run Script Build Phase

  • Paste the following
\#!/bin/sh

INFOPLIST="${SRCROOT}/MyApp/MyApp-Info.plist"
INFOPLIST_WKAPP="${SRCROOT}/MyApp-WKApp/Info.plist"
INFOPLIST_WKEXT="${SRCROOT}/MyApp-WKExt/Info.plist"

PLISTCMD="Set :CFBundleVersion $(git rev-list --all|wc -l)"

echo -n "$INFOPLIST" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"

echo -n "$INFOPLIST_WKAPP" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"

echo -n "$INFOPLIST_WKEXT" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"
  • Navigate to your new BundleVersionRevert target and add a new Run Script Build Phase and paste this:
\#!/bin/sh

INFOPLIST="${SRCROOT}/MyApp/MyApp-Info.plist"
INFOPLIST_WKAPP="${SRCROOT}/MyApp-WKApp/Info.plist"
INFOPLIST_WKEXT="${SRCROOT}/MyApp-WKExt/Info.plist"

PLISTCMD="Set :CFBundleVersion SCRIPTED"

echo -n "$INFOPLIST" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"

echo -n "$INFOPLIST_WKAPP" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"

echo -n "$INFOPLIST_WKEXT" 
| xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"
  • Enjoy!


回答2:

The scheme actions aren't in source control so it's better to add a build phase into your app's target. Syncing the versions across all targets can be solved with a simple script that can be modified for every target you want synced:

  1. Add "New Run Script Phase" in "Build Phases" for your app's target

  1. Rename the script to something like "Sync Versions" and drag it above "Compile Sources" (NOTE: Xcode has a bug that may prevent the drag-drop to work. If so, you'll need to manually edit the .pbxproj file so the build phase goes in the right spot

  2. Paste the following script into the shell:

    INFOPLIST_MYAPP="${SRCROOT}/MyApp/MyApp-Info.plist"
    myAppVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_MYAPP")
    myAppBuild=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_MYAPP")
    
    INFOPLIST_SHAREEXT="${SRCROOT}/ShareExtension/Info.plist"
    /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $myAppVersion" "$INFOPLIST_SHAREEXT"
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $myAppBuild" "$INFOPLIST_SHAREEXT"
    

  1. Build your project as you normally and your share extension's version & build will stay in sync with your main target.


回答3:

The version of your ProjectTodayExtension.appex have to be the same as your app. example:

Target> General:

Version: 1.0 <- change here Biuld: 1.0

If the version of your app to get on itunes connect is 2.3, then you must change the version of your TodayExtension to the same version 2.3.



回答4:

There is a really sweet version management system that Twitch has shared.

Described in this blog post, it is somewhat similar to stk's accepted answer but cleaner and also supports the following:

  • Ties the build number directly (and reversibly) to the git commit before the build. Go back easily to the exact version built for use with crash report.

  • Handles version generation through a target dependency, which is easier to share across multiple targets.

  • Uses C Preprocessor on Info.plist functionality built into Xcode build settings to allow the version numbers to be substituted on the fly, with no modification of the Info.plist file.

It is a little more complex to implement, but it's the best solution I've found, particularly if you have extensions or other targets whose versions must be kept in sync.

Installation Notes: Note the blog does a great job of describing the four shell files, but doesn't really give installation or customization instructions. Here's what I did:

  1. Create a Versions subdirectory at the top level of your project (where the .xcodeproj lives).

  2. Download the four files indicated from the gist link at bottom left of the code samples. Move the four files into your Versions directory.

  3. Using terminal, cd to your Versions directory, then execute the cmd: chmod +x * to make the shell files executable

  4. Now follow the directions in the blog from the start to create your dependency target.

  5. You probably should customize the scripts a bit. I altered the naming and refactored to move the 4 tools to a separate tools directory that I share across projects. YMMV.



回答5:

When trying to validate my archive I got an error message CFBundleShortVersionString missing. To fix the problem I went into Info.plist in the xml code and added CFBundleShortVersionString new version number This produced in plist format Bundle versions string, short This solve my problem