I know you can use the #class word to declare an unknown class in an objective-c header file. Is there a way to declare an unknown enum inside a header class?
For instance, is there a way to prevent the compile error for someEnum?
#import <Foundation/Foundation.h>
#class UnknownClass;
#interface Foo
#property (nonatomic, strong) UnknownClass *someObject;
#property (nonatomic) UnknownEnum someEnum;
#end
Yes you can forward declare an enum:
enum things;
However I think you will run into issues if you start using compiler flags like -pedantic as I don't believe it's part of the ISO standard. I also think, like forward declaring a class, you can probably only use a pointer to it, as its size isn't known.
I've never, personally, ever had to do this and prefer to include the header file defining the enum (and I don't think forward declaring the enum is cleaner than including the file anyway).
Bottom line: Don't bother.
If you for some reason you do not want to add the #import or #include directive for the header that does declare the enum, then just type it as something else. All enum types are pretty limited to some form of int. Just declare it as similar. If you know you will get 0 or higher you could use NSUinteger. If you know you will get negative numbers, use NSInteger.
Either of those should be sufficient for your property declaration.
That is to say, named enums are nothing more than typdefs as far as using the value of an enum member or assigning that value to a variable.
Another option is to do #ifndef to define the self same type def.
Related
I have a simple Blocks and typedef doubt.
Consider the following codes, I've some typedef and two methods, second one is commented out. My doubt is regarding the first one. Should I use this one? Any issues or something that may arise in future?
typedef void (^MySuccessBlock)(MyServiceResponse *response);
typedef void (^MyFailureBlock)(NSError *errorObject);
#property (nonatomic, copy)MySuccessBlock mySuccessBlock;
#property (nonatomic, copy)MyFailureBlock myFailureBlock;
//SHOULD I USE THIS?
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
//- (void)myServiceWithCompletion:(void (^)(MyServiceResponse *response))completion
// failure:(void (^)(NSError *errorObject))failure;
In Implementation file:
//If 1st one is used:
- (void)myServiceWithCompletion:aSuccessBlock
failure:aFailureBlock{
self.mySuccessBlock = aSuccessBlock;
self.myFailureBlock = aFailureBlock;
....
}
You should use this:
- (void)myServiceWithCompletion:(MySuccessBlock)successBlock
failure:(MyFailureBlock)failureBlock;
Note the capitals at the beginning of MySuccessBlockand MyFailureBlock as in your typedef.
In fact, when you declare:
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
the problem comes from the fact that you don't specify the type of your parameters 'mySuccessBlock' and 'myFailureBlock'. So they are treated as default type id because:
If a return or parameter type isn’t explicitly declared, it’s assumed
to be the default type for methods and messages—an id.
It is like if you write:
- (void)myServiceWithCompletion:(id)mySuccessBlock
failure:(id)myFailureBlock;
id type is a pointer, and blocks are pointers, so there is no compile problem. But you can have execution problem because of black's parameters and return value!
The typedef declaration provides a way to create an alias that can be used anywhere in place of a (possibly complex) type name. See
You should use the typedef in the following way.
- (void)myServiceWithCompletion:(MySuccessBlock)aSuccessBlock
failure:(MyFailureBlock)aFailureBlock;
I've noticed that I get compilation errors if I place certain declarations in certain places in my header file. I've put comments into the code as to where I think certain things go; are they correct?
#interface Level : CCNode {
//Instance variables?
PlayBackgroundLayer* playBGLayer;
PlayUILayer* playUILayer;
PlayElementLayer* playElementLayer;
}
//Static methods?
+(void) InitLevel: (int) levelNumber;
+(Level*) GetCurrentLevel;
//Property declarations for instance variables?
#property (nonatomic, retain) PlayBackgroundLayer* playBGLayer;
#end
//Static variables?
Level* currentLevel;
PlayTilemapLayer* playTilemapLayer;
You are correct on all counts except one. Your last variables are not static variables, they are global variables. Static variables are simply variables that are declared with the static keyword and they mean something a little different than other languages. They aren't class variables, they are variables that are visible only to the file that they are declared in, and only then in the scope that it was declared (if you declare it inside a function other functions won't see it). However, as you would expect, they are only declared once regardless of how many instances you have. If you declare something outside an interface without the static keyword as you did, other classes will import them. However, this is not the ideal way to accomplish this (you might get redefinition errors if more than one class imports this header).
Also, one caveat, is that properties don't need to have an explicit backing variable (the compiler will create one for you if you use the #synthesize keyword), but of course if you desire one there is nothing wrong with it.
Finally, you should note that the only reason that your static methods class methods are not instance methods is because they start with a plus (+) character as opposed to a minus (-) character.
Instance variables usually don't need to be declared explicitly. They're created when you #synthesize the property. If you do want them, though, the (new) correct place* is at the top of the implementation block:
#implementation Level
{
PlayBackgroundLayer* playBGLayer;
PlayUILayer* playUILayer;
PlayElementLayer* playElementLayer;
}
Those aren't static methods, they're class methods, but, yes, that's where you declare them. Some people like to put #property declarations before the class methods, but that's a matter of opinion. Instance methods go after both of these, although technically speaking the order doesn't matter -- that is, the compiler doesn't care, it's just a matter of readability.
Those top-level variables need to go somewhere other than a header file, though. If you put them there you will get compilation errors because every file that imports the header will appear to be re-declaring storage for those variables, which isn't allowed.
Ususally you put such variables into a .m file. If you want them to only be visible from there, you would use static. If you want them visible from other files that import the header, you leave static off and declare the variable as extern in the header:
extern Level* currentLevel;
This lets the compiler know that the storage for the variable is reserved elsewhere.
*See "Class Interface" in TOCPL.
How to declare an array of characters so that all the functions that has been defined inside the class can use it with the updated values.
Getting errors when defining the char data[4096] in the #synthesize definition.
#interface A: NSObject
{
char data[4096];
}
#property(nonatomic,retain)char data;
#end
#implementation A
#synthesize data
#end
I am getting "No declaration of the property 'pData' found in the interface"
Not sure why you get that error, but several things are clearly wrong in your code:
data instance variable and property for it have different types. Property declaration should be
#property(nonatomic) char[4096] data;
You must use retain attribute only for obj-c types properties, for plain c-types use assign (or don't specify anything as assign is used by default)
Exposing your pointer to char directly to changes may be not a good idea - better make your property readonly and make special method to change its contents:
#property(nonatomic, readonly) char[4096] data;
- (void) changeData:...//some parameters here
P.S. May be consider using NSString* (or NSMutableString*) instead of char[]?
P.P.S. Or if you just store some random byte data consider using NSData/NSMutableData for that. (Thanks #bbum for suggesting that)
This is just out of curiosity but when i declare an enum type, would it be better to have it within an implementation declaration or outside of it? What would be best practice? For example:
#implementation PostQuestionScene
enum popUpItems{
kExpiredBox,
kPauseBackground
};
vs..
enum popUpItems{
kExpiredBox,
};
#implementation PostQuestionScene ..
I tend to always have a typedef so it's just like another variable:
typedef enum {
kExpiredBox,
kPauseBackground
} popUpItems_t;
Then create instances of it.
popUpItems_t popUpItems;
If you will use it outside that module, put the typedef in the header so when the header is included, other modules have the typedef at their disposal (if they need to take it as an argument, for example,) otherwise put it in the implementation (think public/private variables.)
I don't think it makes any technical difference. I would place it before the #implementation (along with all other miscellaneous declarations) unless it is just used in one or a small group of methods, in which case I would place it immediately before those methods.
Of course, if it might be used by clients or subclasses it should be in your header file (where #interface is) so that the definition is visible to them.
I am working my way through some Objective-C code that I did not write and have found a variable declaration style that I am unfamiliar with. Can anyone tell me the scope of the variable 'myVar' in the class implementation below? Note that this appears in the '.m' file and not the interface declaration.
#implementation MyClass
#synthesize ivar1, ivar2;
NSString* myVar; // <- What is the intent?
- (id)init {
...
#end
To me the intention appears to be similar to that of a member variable. What are the advantages of declaring a variable in this way instead of using an ivar in the #interface declaration?
It's just a plain old global variable. There's only one instance of it, and it can be accessed by any code within the same file translation unit (the final file you get after running the preprocessor). Other translation units (that is, other .m files) can also access that global variable, but in order to do so, they need to use an extern statement:
extern NSString *myVar;
extern says "this is the name of a global variable, but it's defined in a different translation unit". The linker resolves all of the extern declarations at link time.
a poorly named global variable...
I'm not too experienced in ObjC but I'd say that is a global.