When I am using this method class_getName(), i find it is declared like this:
**OBJC_EXPORT** const char *class_getName(Class cls)
What does OBJC_EXPORT mean?
If you CMD+CLICK on the symbol, you'll see it's not a keyword. OBJC_EXPORT is defined as:
#define OBJC_EXPORT OBJC_EXTERN OBJC_VISIBLE
And OBJC_EXTERN is either extern "C" or extern, depending on if you're compiling C++ or C, respectively.
And OBJC_VISIBLE is either __declspec(dllexport) or __declspec(dllimport) on Windows, or __attribute__((visibility("default")) otherwise.
Basically it's saying you can link that symbol externally.
Here's the full listing:
#if !defined(OBJC_EXTERN)
# if defined(__cplusplus)
# define OBJC_EXTERN extern "C"
# else
# define OBJC_EXTERN extern
# endif
#endif
#if !defined(OBJC_VISIBLE)
# if TARGET_OS_WIN32
# if defined(BUILDING_OBJC)
# define OBJC_VISIBLE __declspec(dllexport)
# else
# define OBJC_VISIBLE __declspec(dllimport)
# endif
# else
# define OBJC_VISIBLE __attribute__((visibility("default")))
# endif
#endif
#if !defined(OBJC_EXPORT)
# define OBJC_EXPORT OBJC_EXTERN OBJC_VISIBLE
#endif
If you have three class named A,B and C respectively and all three classes are unrelated(i mean not in inheritance hierarchy) and you just want to access the value declared in A, then extern is a more appropriate way to go. In this case, you want to declare the variable as extern in ClassA.h, then define it in Class.m. As long as ClassB and ClassC import ClassA.h, they will be able to link against the same extern definition.
Instead of using extern by itself, it's more robust to use OBJC_EXPORT, which is defined in objc-api.h and handles compiling under C++ as well. Here's a code sample:
// ClassA.h
OBJC_EXPORT NSString* commonString;
...
// ClassA.m
NSString* commonString = #"OldValue";
// ClassB.m
#import "ClassA.h"
...
commonString = #"NewValue"; // Can be inside a function or method
Reference : this so post
Related
I've found that there is a UIKIT_DEFINE_AS_PROPERTIES macro in a lot of places in system's headers like this:
#if UIKIT_DEFINE_AS_PROPERTIES
#property(class, nonatomic, readonly) UIDevice *currentDevice;
#else
+ (UIDevice *)currentDevice;
#endif
But I cannot find the value of it.
what's the use for UIKIT_DEFINE_AS_PROPERTIES and where is it defined?
It is for swift?
UIKIT_DEFINE_AS_PROPERTIES is defined in <UIKit/UIKitDefines.h> as
#if (!defined(SWIFT_CLASS_EXTRA) || (defined(SWIFT_SDK_OVERLAY_UIKIT_EPOCH) && SWIFT_SDK_OVERLAY_UIKIT_EPOCH >= 1))
#define UIKIT_DEFINE_AS_PROPERTIES 1
#else
#define UIKIT_DEFINE_AS_PROPERTIES 0
#endif
The SWIFT_CLASS_EXTRA and SWIFT_SDK_OVERLAY_UIKIT_EPOCH macros
control how Objective-C code is imported into Swift, compare ClangImporter.cpp.
I have several targets and depending on them I need to import headers. I can do this by defining some preprocessor value and then check it with #ifdef, but I'm wondering, if there any way to do something like:
#if TARGET_NAME = "FirstTarget"
#import "SomeHeader.h"
#endif
u can use like below for example,
//Your current target's are defined
#define FIRST_TARGET "FirstTarget"
#define SECOND_TARGET "SecondTarget"
#define THIRD_TARGET "ThirdTarget"
//set which target u want to run
#define TARGET_NAME FIRST_TARGET //SECOND_TARGET //THIRD_TARGET
//use like below
#if (TARGET_NAME == FIRST_TARGET) //or u can directly specify name instead of defining at the beginning
#import "SomeHeader.h"
//other headers
#elif (TARGET_NAME == SECOND_TARGET)
//header to be in second target
#elif (TARGET_NAME == THIRD_TARGET)
// other header
#endif
Edit:
i got it, it gives error because macros doesn't compare variable length values, for more details see this hear .
so in order to work u can change it like below,
//Your current target's are defined, instead of strings give some constant values
#define FIRST_TARGET 1//#"FirstTarget"
#define SECOND_TARGET 2//#"SecondTarget"
#define THIRD_TARGET 3//#"ThirdTarget"
//set which target u want to run
#define TARGET_NAME FIRST_TARGET //SECOND_TARGET //THIRD_TARGET
//use like below
#if TARGET_NAME == FIRST_TARGET
#import "SomeHeader.h"
//other headers
#elif (TARGET_NAME == SECOND_TARGET)
//header to be in second target
#elif (TARGET_NAME == THIRD_TARGET)
// other header
#endif
I have a define variable is a string like this
#define kyouTubeLink #"<iframe width='%d' height='%d' src='http://www.youtube.com/embed/%#?showinfo=0&modestbranding=1&rel=0&showsearch=0' frameborder='0' scrolling='0' allowfullscreen></iframe>";
so how to call this variable in another file.Thanks in advance
You cannot reference a variable that is #define-d in another translation unit. You can put the definition in a header file, and #include it from any translation unit that needs the definitions.
Since the definition is a C string literal, though, you would be better off defining a constant extern variable for it, putting the declaration in a header, defining it in one of your translation units, and using everywhere else:
Common header (say, "YouTubeShared.h"):
extern const NSString* kyouTubeLink;
First translation unit (e.g. "AppDelegate.m" or whatever is a file that is better suited to hold the constant)
#include "YouTubeShared.h"
const NSString *kyouTubeLink = #"<iframe width='%d' height='%d' src='http://www.youtube.com/embed/%#?showinfo=0&modestbranding=1&rel=0&showsearch=0' frameborder='0' scrolling='0' allowfullscreen></iframe>";
... // More things go here
Second translation unit:
#include "YouTubeShared.h"
... // More things go here
NSString *res = [NSString stringWithFormat:kyouTubeLink, 123, 456];
Hi I'm a newbie to objective-C ,today I was learning the concept of dynamic typing and binding, all was well until I wrote and executed this program
#import <Foundation/Foundation.h>
#interface A:NSObject
#property int var;
-(int)add:(A*)argObj;
#end
#implementation A
#synthesize var;
-(int)add:(A *)argObj
{
return (self.var + argObj.var);
}
#end
#interface B:NSObject
#property double var1;
-(double)add:(B *)argObj;
#end
#implementation B
#synthesize var1;
-(double)add:(B *)argObj
{
return (self.var1 + argObj.var1);
}
#end
int main()
{
#autorleaease{
id data1, data2;
A * aobj1 = [[A alloc]init];
aobj1.var = 30;
A * aobj2 = [[A alloc]init];
aobj2.var = 50;
data1 = aobj1;
data2 = aobj2;
NSLog(#"The sum of two A objs is : %i",[data1 add: data2]);// prints 80 which is correct
B * bobj1 = [[B alloc]init];
bobj1.var1 = 5.5;
B * bobj2 = [[B alloc]init];
bobj2.var1 = 5.5;
data1 = bobj1;
data2 = bobj2;
NSLog(#"The sum of 2 B objs is : %f",[data1 add: data2]);// prints 0.0000 why so ????
}
return 0;
}
I got the output when I executed add method on class A objects however when I executed the add method on class B I got the wrong answer. Why is this??
And this is how my output looked . In the output the compiler warned me like this
main.m: In function 'main':
main.m:47:5: warning: multiple methods named '-add:' found [enabled by default]
NSLog(#"The sum of two A objs is : %i",[data1 add: data2]);
^
main.m:8:1: note: using '-(int)add:(A *)argObj'
-(int)add:(A*)argObj;
^
main.m:8:1: note: also found '-(int)add:(A *)argObj'
main.m:26:1: note: also found '-(double)add:(B *)argObj'
-(double)add:(B *)argObj;
^
main.m:55:5: warning: multiple methods named '-add:' found [enabled by default]
NSLog(#"The sum of 2 B objs is : %f",[data1 add: data2]);
^
main.m:8:1: note: using '-(int)add:(A *)argObj'
-(int)add:(A*)argObj;
^
main.m:8:1: note: also found '-(int)add:(A *)argObj'
main.m:26:1: note: also found '-(double)add:(B *)argObj'
-(double)add:(B *)argObj;
^
Executing the program....
$demo
2014-01-20 04:06:05.788 demo[30357] The sum of two A objs is : 80
2014-01-20 04:06:05.789 demo[30357] The sum of 2 B objs is : 0.000000
The compiler was saying multiple methods exist but these methods are entirely belongs to different class and while we use dynamic typing and dynamic binding the call will get resolved properly right ?? So why am I getting an output like this? Thanks in advance.. :)
The problem is not really about dynamic binding (which works as expected) but about passing the parameters. Ambiguous selectors prohibit that the compiler knows which prototype to use.
Objective-C uses C's ABI for function/method calling and argument passing. The compiler has to know the types of the arguments. If an variable is not strongly typed the compiler can not look up the correct selector. If the parameters are not compatible (as in your case) this will lead to undefined behavior.
Edit: The compiler actually tells you all about the confusion:
> main.m:47:5: warning: multiple methods named '-add:' found
> NSLog(#"The sum of two A objs is : %i",[data1 add: data2]);
> [...] note: using '-(int)add:(A *)argObj'
This is for the first use when adding two As. The compiler informs you that it used the class A variant for the call which is, by coincidence, correct.
> main.m:55:5: warning: multiple methods named '-add:' found
> NSLog(#"The sum of 2 B objs is : %f",[data1 add: data2]);
> [...] note: using '-(int)add:(A *)argObj'
That's the second log call with two B objects. Again the compiler complains that there's the ambiguity with the two add: selectors and informs you that it, again, chose the A variant. This time that's the wrong option and you see the unexpected results during runtime.
I have a large enum (for the sake of transparency 63 values), and I am now creating a NS_Options bitflag based on that enum. Is there a way that I can write this so that it will be flexible?
The main concerns I have with hardcoding it are:
If I add/remove an enum, I will have to manually add/remove it in my bitflag.
There is a lot of typing to generate these.
My .h file is getting intensely long (because I like to use whitespace and adequate comments)
The only solution I've come up with thus far is:
#define FlagForEnum(enum) 1 << enum
typedef NS_ENUM(NSInteger, ExampleEnum)
{
Value1,
Value2,
...
ValueN
}
typedef NS_OPTIONS(NSNumber, ExampleEnumFlags)
{
Value1Flag = FlagForEnum(Value1),
Value2Flag = FlagForEnum(Value2),
...
ValueNFlag = FlagForEnum(ValueN)
}
This is a barely adequate solution when I remove an enum (at least I get a compile error), and if the enum ordering gets changed, the flags' bitshifted position changes too (not that it truly matters, but it seems comforting). But it doesn't solve the 'this-is-a-lot-of-typing' problem, or the 'what-if-I-forget-to-add-a-flag' problem.
You can use a technique called X Macro
#define VALUES \
VALUE_LINE(Value1) \
VALUE_LINE(Value2) \
VALUE_LINE(Value3)
typedef NS_ENUM(NSUInteger, ExampleEnum)
{
#define VALUE_LINE(x) x,
VALUES
#undef VALUE_LINE
}
typedef NS_OPTIONS(NSUInteger, ExampleEnumFlags)
{
#define VALUE_LINE(x) x##Flag = 1 << x,
VALUES
#undef VALUE_LINE
}
Here is a slightly better (in terms of less typing) preprocessor #define solution. Although this still isn't as elegant as I'd like.
#define BitShift(ENUM_ATTRIBUTE) (1 << ENUM_ATTRIBUTE)
#define CreateEnumFlag(ENUM_ATTRIBUTE) ENUM_ATTRIBUTE##Flag = BitShift(ENUM_ATTRIBUTE)
typedef NS_ENUM(NSUInteger, ExampleEnum)
{
Value1,
Value2,
...
ValueN
}
typedef NS_Options(NSUInteger, ExampleEnumFlags)
{
CreateEnumFlag(Value1),
CreateEnumFlag(Value2),
...
CreateEnumFlag(ValueN)
}
This will create flags of the form Value1Flag, Value2Flag, ..., ValueNFlag.