I'm trying to create an embedded framework for use with iOS8. After creating one called SampleKit (BTW; is there any convention here, should I used a prefix?), it contains a header file that is puzzling me:
//! Project version number for SampleKit.
FOUNDATION_EXPORT double SampleKitVersionNumber;
//! Project version string for SampleKit.
FOUNDATION_EXPORT const unsigned char SampleKitVersionString[];
I know that FOUNDATION_EXPORT is a macro for extern or extern "C", but I'm not sure about the two constants. Where am I supposed to set the value for them?
Project > Build Settings > Versioning > Current Project Version :
Related
This question already has an answer here:
Force Header Files to Compile as C++ in Xcode
(1 answer)
Closed 2 years ago.
I'm trying to use a 3rd party sample code as part of my Objective-C application.
However, when trying to compile my project I get a lot of compiler errors.
The objc syntax that is used in the sample is quite strange and I believe that it is compiled as something else within the project.
For example, as part of the header file the struct definition has default values:
File.h
struct Options
{
int count = 100;
}
...
In their project, the above header file would compile just fine, but when I try to compile it I see an Xcode error:
Expected ';' at end of declaration list
I'm not an objective-c expert, but from what I've read and also found as part of other posts data types cannot have default values, but somehow it compiles fine in the Xcode sample app.
Please let me know if you need more info or other examples of what would compile fine in their project and doesn't work when I copy and paste the code into mine.
Edit:
Force Header Files to Compile as C++ in Xcode
Individually header files doesn't compiled. Compiled source files where they included. If you include them in .c they will be compiled like C, if in .m - like Objective-c, if in .cpp - like C++, if in .mm - like Objective-C++.
My issue was that I was using this header file into a .m file which compiles it to an Objective-C standard. When I change the extension to .mm everything worked fine.
When you think of objective-C as actually being C its more clear why defaults are not set in .h files
This does not apply to the rules of default sizes which are needed when no flexible memory allocation for a data type is available by default, like for (as is) most data types in C.
Even this two sentences already show the difficulty to distinguish what is meant with "default".
Which is why you end up with definition of initiation processes and functions to declare what exactly is "default" in the other file.
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int count;
} Options;
typedef struct {
int foo;
Options bar[100];
} Foo;
struct Bar {
Foo lotsof;
}
void MyInitiationFunction(Bar *b);
// definition of MyInitiationFunction in .m/.c file
#ifdef __cplusplus
}
#endif
but there is the concept of enum that can trick your mind where defined enumeration default states are what you build some stuff on, which is not a value.
After I upgraded to El Capitan and Xcode 7, I cannot build my app. I keep getting duplicate symbols on all of my global variables. Please help.
enter image description here
//Global.h
#ifndef Global_h
#define Global_h
extern NSInteger pickerConstantOne, pickerConstantTwo,numberOfDays, monthOfToday;
NSInteger pickerConstantOne, pickerConstantTwo,numberOfDays, monthOfToday;
#endif /* Global_h */
You have misdeclared those variables; remove this statement from the header:
NSInteger pickerConstantOne, pickerConstantTwo,numberOfDays, monthOfToday;
and move it into a .m file.
You should also review exactly why you are using global variables in the first place as you certainly don't need to be.
Cocoa Touch Frameworks provide support for versioning, which can be found in Build Settings under the Versioning section.
To access this value at runtime, we can use the FrameworkVersionNumber and FrameworkVersionString[] variables which are auto-generated for us as part of the build process.
When working with a Swift project, these can be found auto-generated at the top of the Objective-C compatibility header:
//! Project version number for Framework.
FOUNDATION_EXPORT double FrameworkVersionNumber;
//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
However, whilst FrameworkVersionNumber is accessible from Swift, FrameworkVersionString[] is not. In fact looking at the contents of the framework module, I can see that only the first variable is exposed to Swift:
//! Project version number for Framework.
var FrameworkVersionNumber: Double
The problem with this is that since FrameworkVersionNumber is a Double, any version numbers like 3.2.1 simply get changed to 3.200000...
Does anyone know whether this is a flaw in my project setup, a bug in Xcode, or whether there is a way of getting the framework version in Swift as a String or array, so that I can provide more granular versioning than major.minor?
I have actually found a potential workaround for this issue, it's not so clean but it does work:
By default, when Xcode creates a framework it sets the Version to 1.0 and the Build to $(CURRENT_PROJECT_VERSION) which is great, because this value is actually being copied from the Current Project Version field in Build Settings > Versioning.
So what you can do to get this value at runtime is as follows:
let bundle = NSBundle(identifier: "com.yourframework.Framework")! // Get a reference to the bundle from your framework (not the bundle of the app itself!)
let build = bundle.infoDictionary![kCFBundleVersionKey] as! String // Get the build from the framework's bundle as a String
This does work but it feels quite circuitous for something that used to (I believe) be readily accessible from a variable in Objective-C.
IMPORTANT UPDATE - OCT 2021 - XCODE 13
When submitting an app to the App Store, Xcode 13 has a new option called "Manage Version and Build Number" which is ticked by default. If left checked, Xcode will automatically set your app's version number which (rather counter-intuitively), will also apply to all included frameworks. In other words, if your app version is 1.0, your framework version will be overwritten with 1.0.
Make sure you disable this option to avoid your framework version being overwritten.
You can also opt-out of this new behaviour by setting manageAppVersionAndBuildNumber in your export options plist.
For further details, see this discussion on the Apple Developer Forums.
These variables are populated in an automatically generated .c file when building from the project's CURRENT_PROJECT_VERSION. It looks like this:
extern const unsigned char FrameworkVersionString[];
extern const double FrameworkVersionNumber;
const unsigned char FrameworkVersionString[] __attribute__ ((used)) = "#(#)PROGRAM:Mark2SDK PROJECT:Framework-1" "\n";
const double FrameworkVersionNumber __attribute__ ((used)) = (double)1.;
The C array doesn't make it to Swift for some reason. Modifying the array definition to a pointer causes an EXC_BAD_ACCESS crash. What you can do though is create a pointer to the array and use that. In Framework.h:
//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
// add this
extern const unsigned char * FrameworkVersionStringPtr;
Then, either by creating Framework.c or in another c or m file, add this:
#import "Framework.h"
const unsigned char * FrameworkVersionStringPtr = FrameworkVersionString;
You can then use the string pointer in Swift to get the version:
func version() -> String? {
let ver = String(cString: Mark2SDKVersionStringPtr)
guard let range = ver.range(of: "-") else {
return nil
}
return String(ver[range.upperBound...])
}
print(version())
// 1.0.1
for swift 4.2 it works:
if let bundle = Bundle(identifier: "com.ingconti.SampleFramework") {
if let build = bundle.infoDictionary?["CFBundleShortVersionString"] {
print(build)
}
}
I'm using Xcode6 GM to create a Coacoa Touch Framework (a new function in Xcode6), then this framework is included into my app.
Everything is fine (works fine), except that I get warnings in "#import". What is the root cause?
I ran into the same problem and eventually fixed it by adding my project headers into the umbrella header. When you create a new framework it should start with a single .h file titled by the project (in your case DirectProximityFramework.h).
Inside this file is a comment:
In this header, you should import all the public headers of your
framework using statements like #import <DirectProximityFramework/PublicHeader.h>
So just add your GeofencingHelper.h file in this file:
#import <DirectProximityFramework/GeofencingHelper.h>
This should remove all of your warnings!
Maybe, you can stop this warning by adding following line to "DirectProximityFramework.h"
#import <DirectProximityFramework/GeofencingHelper.h>
...etc
I suggest to check
[Target your framework] -> Build Phases -> Headers -> Public
In case if it is not your framework and there is nothing to do you can disable warning in such way
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-umbrella"
#import <DirectProximityFramework/GeofencingHelper.h>
#pragma clang diagnostic pop
Note - it is not a fix, it just hide the problem.
I ran into this issue and all the solutions above didn't fit me, since the file wasn't supposed to be in the umbrella header.
So if this is your own framework and that particular file shouldn't be in the umbrella header, make sure it isn't marked public in the target membership section.
That fixed it for me.
I had same issue and my solution was..
When you create the framework project.Your project automatically "yourProjectName.h" file gets created, In this header file import class class.
In my case I am getting missing submodule 'MSFramework.MSLocationManager' [-Wincomplete-umbrella]this warning.
resolved by Just importing
#import <UIKit/UIKit.h>
# import "MSLocationManager.h"
//! Project version number for MSFramework.
FOUNDATION_EXPORT double MSFrameworkVersionNumber;
//! Project version string for MSFramework.
FOUNDATION_EXPORT const unsigned char MSFrameworkVersionString[];
here I just add the # import "MSLocationManager.h"in header file.
// In this header, you should import all the public headers of your framework using statements like
#import <GameworkSDK/GWObject.h>
like this:
#import <UIKit/UIKit.h>
#import <GameworkSDK/GWObject.h>
//! Project version number for GameworkSDK.
FOUNDATION_EXPORT double GameworkSDKVersionNumber;
//! Project version string for GameworkSDK.
FOUNDATION_EXPORT const unsigned char GameworkSDKVersionString[];
i had this problem cocoa pods
my solution was real simple but took forever for me to figure out.
when i ran $ pod install it generated a workspace for me in the same dir as my .xcodeproj file.
however i had already created a workspace to use as its parent directory.
so then i simply deleted my old workspace and went with the one that pods created
glhf!
Set header search path in your project setting:
TARGETS / Build Settings / Header Search Paths
"$PODS_CONFIGURATION_BUILD_DIR/[YOUR PROJ NAME]/[YOUR PROJ NAME].framework/Headers"
Now import the header file.
#import <DirectProximityFramework.h>
This question already has an answer here:
"FOUNDATION_EXPORT" vs "extern"
(1 answer)
Closed 9 years ago.
What is the use of FOUNDATION EXPORT in Objective-c?
So I have:
KError.h
FOUNDATION_EXPORT NSString *const KAPPErrorDomain;
enum {
KPUnexpectedError = -1,
};
KError.m:
#import "KError.h"
NSString *const KAPPErrorDomain = #"com.kexample.myapp";
I assume that when you use Foundation_export in this case, it is to be able to use a variable in another file?
So that in KService.m, I cam reference KAppErrorDomain without any problem?
Yes. FOUNDATION_EXPORT is a macro that expands to extern
(or extern "C" in a C++ file), and that is the
keyword to declare a variable that is shared across source files (better: shared
across "translation units").
See How do I use extern to share variables between source files?
for many good answers why extern is necessary and how it works.