Xcode 13 introduced a new behavior that breaks framework versions: When your clients upload their app, Apple changes the CFBundleShortVersionString of all frameworks to match that of the app.
(See this StackOverflow thread for example)
One way to avoid that is to hard-code your framework version. But if you you want to keep using the MARKETING_VERSION build setting, you can use the following hack.
Create a version variable for your framework, for example:
public class MyFramwork: NSObject {
@objc static var version: String = ""
}
Then include this Objective-C file in your framework:
#import <MyFramwork/MyFramwork-swift.h>
#define PROCESSOR_STRING(x) PRE_PROCESSOR_STRING_LITERAL(x)
#define PRE_PROCESSOR_STRING_LITERAL(x) @#x
@interface MyFramwork(version)
@property (class) NSString *version; // to access internal property
@end;
@interface MyFramworkLoader: NSObject
@end
@implementation MyFramworkLoader
#ifdef MARKETING_VERSION
+ (void)load {
dispatch_async(dispatch_get_main_queue(), ^{
MyFramwork.version = PROCESSOR_STRING(MARKETING_VERSION);
});
}
#endif
@end
This will assign the MARKETING_VERSION value that you built you framework with, instead of an Apple-manipulated CFBundleShortVersionString value.




The private API
Some actions may sometimes have more than one possible target, and other times only one.
Or picking an image. If you’re running on a camera-less iPod, you just show a UIImagePickerController to pick from the photo library. But with a camera, and maybe an existing image to delete, you’ll want to show an action sheet to choose the actual action that your “Photo” button performs.