Do you have to declare overriden #property methods in the .h file? - objective-c

Beginner question here. In the .h file of an objective c class..
If you have an #property int someVar; for example.. and you're actually going to write the setter method yourself in the .m file.. do you still have to declare that setter method in the .h file?
If you have some #property declarations in the .h file and you are writing the getters and/or setters yourself.. you don't have to #synthesize them, correct? And if you don't synthesize them, do you have to declare them in the .h file or does the fact that making them properties is sufficient?

No, you don't have to define them since they already are defined. Defining a property implies that there will be a setter method – unless that property is readonly.
Just replace the #synthesize with #dynamic and implement getter and setter yourself.

Related

Is following use of objc #protected directive safe/legit?

I have to expose a private property to sub-classes.
Since there is no such thing as "protected properties" in objc AFAIK, I'm using the #protected directive to expose the corresponding ivar that's synthesised by the complier.
This method appears to work, however, I'm not sure if I'm affecting the synthesis of the property and ARC in some inadvisable way?
I'm using a weak property here to show how the compiler forced me to use __weak modifier with the #protected directive, i.e. it appears the complier is aware of the two declarations and the link between them.
Superclass .h file
#interface Superclass : NSObject
{
#protected
SCNScene * __weak _scnScene;
}
#end
Superclass .m file
#interface Superclass ()
#property (weak, nonatomic) SCNScene * scnScene;
#end
#implementation Superclass
........
#end
Subclass .m file
#implementation Subclass
// Can use _scnScene just fine
_scnScene = .....
#end
Yes, it'll probably work. Don't do it this way. It's very inflexible. It forces you to declare ivars in the header, it only works with ivars, and it doesn't give you any control over read/write controls (or let you create a custom getters/setters). There isn't really a good reason to use the # access controls anymore (not since the move to non-fragile ivars, and they weren't that useful before).
A typical way to do this is with a +Protected header with a category. For example, you'd create a header file Superclass+Protected.h like this:
#interface Superclass (Protected)
#property (weak, nonatomic) SCNScene * scnScene;
#end
Then you import that into any implementation files that are allowed to access scnScene. Note that you could make this readonly if you wanted, so internally it's writable, but to protected implementations it's only readable, and to the public, it's invisible.
This is more flexible than literal "protected" because you can import this header into any other implementation where it is appropriate. So it can also be the equivalent of C++'s "friend." Obviously naming the file and providing some header comments can be helpful to let callers know if they should or shouldn't import this file.
To any complaints that this doesn't enforce access controls (not that you made any, but for anyone that does), neither does #protected. If I call valueForKeyPath:, I can access protected ivars, too. ObjC helps you create "no trespassing signs" so that callers know when they're in places they shouldn't be. It doesn't try to stop programs from accessing their own memory space. (This would be a futile goal; you can always read private variables and call private functions in any language that allows raw memory access; the point of access controls is to help callers write correct code, not stop them from doing anything.)
In the context of a class declaration, protected is the default visibility for instance variables, so your declaration has no effect. In fact, the following declaration:
#interface Superclass : NSObject
#end
would have the precisely the same effect as the declaration you posted, because the compiler automatically synthesizes any needed ivars for declared properties, unless you declare them yourself.

What's the difference between #interface or #implementation being in .h or .c [duplicate]

This question already has answers here:
Difference between #interface definition in .h and .m file
(3 answers)
Closed 9 years ago.
I'm playing around with some code in a Kobold2D example project (Orthogonal Tile based Game) and I've noticed:
#interface TileMapLayer : CCLayer //Map
{
float tileMapHeightInPixels; //depricated#interface TileMapLayer()
}
#end
in the TileMapLayer.h file, and:
#interface TileMapLayer()
#property (strong) HUDLayer *hud;
#property (strong) CCTMXTiledMap *tileMap;
#property (strong) CCTMXLayer *background;
#property (strong) CCTMXLayer *foreground;
#property (strong) CCTMXLayer *meta;
#property (strong) CCTMXLayer *base;
#property (strong) CCSprite *player;
#property (strong) CCSprite *playerTurret;
#property (assign) int money;
#end
in the TileMapLay.m file.
I've always thought that .h files hold interfaces and .m files store implementations
Can someone please explain their purpose (started from the basics, I'm still learning Objective C) and what the difference in purpose between the 2 examples above?
What you put in a header and implementation file is entirely up to you. They all get concatenated by the preprocessor before compilation anyway. It's convention to put external interfaces that other compilation units might want to use into header files. The person who wrote your example code intends to keep all of those properties defined in the .m file private - that is they're intended to not be directly accessed by other code in the system.
First notice that .m are Objective-C files (which can have both Objective-C and C) and .c are plain C files which can only contain C code. Both employ the .h extension for the header.
Regarding Objective-C, the .m file does #interface TileMapLayer() to declare a class extension. A class extension can add ivars and properties to a Class that was already declared in the .h file. An extension is only viewable from within its own .m file. It doesn't make much sense to declare an extension inside an .h file, but I guess you could if you wanted.
Regarding purpose, a recommended practice is declaring the minimum amount of properties needed in the .h in order to keep the interface lean and clean. For properties that are only needed inside the class, you can declare them in the extension on the .m file. My personal preference is to avoid explicitly declaring and using ivars at all (unless I'm overriding a property setter or getter), because that way on the implementation I can tell at first glance which variables are local to the function or object properties. The overhead is usually negligible and I prefer to code for readability than to prematurely optimize. With the recently introduced auto-synthesized properties this saves a lot of boilerplate code as well.
A strategy that I also recommend is thinking carefully which properties should be modifiable from outside the object or not. Declare the non-modifiable properties as readonly in the .h files. Then, you can re-declare them as readwrite in the .m extension for operations from the object itself. This ensures that you or your colleagues don't commit the mistake and modify a readonly property that is not supposed to change from outside the object. In a sense it helps you in keeping the logic of the object inside it. I would try to avoid the trap of declaring everything readwrite (the default), because then it usually comes to bite you back later.
Things defined in .h can be used by any .m files as long as the .m includes the .h. But things defined in .m can only be used in current .m file.

Is modern Objective-C convention really to not have any ivars that aren't properties? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
iOS: must every iVar really be property?
I just read a book that said that modern convention is not to declare any ivars at all in your .h file between curly braces, and instead to make everything properties.
I want to make sure this is true even in trivial cases. I am making a class where there is a BOOL named "recording" which says whether the device is currently recording some video. This isn't something that other classes need, and my incline is to just put it as a BOOL in the header then refer to it in the .m file in the 2 spots where it is needed.
However, I also want to do things the accepted, right way. But I don't see why I make it a public property?
What you read is wrong, plain and simple.
Modern convention is to skip ivars when there is a corresponding property that can synthesize them. Additionally, with recent versions of LLVM it is possible to move your ivars to your implementation file (as #DrummerB has already mentioned) so that the header contains no ivars. That's considered good practice because it doesn't expose internal workings of the class.
But have no ivars at all and a property for everything that was an ivar? Nope, not normal Objective-C.
Your book is right (and wrong). Don't declare ivars in your headers anymore. That's only supported for compatibility reasons. But also don't declare properties for private variables.
If you want do declare a private ivar that other classes don't need to use, declare them in your implementation file:
// MyClass.m
#implementation {
BOOL recording;
}
// methods
#end
I recommend to not use ivar at all. Instead you can create a class extension in which you will declare properties that has to be hidden:
#interface MyClass ()
#property (nonatomic, assign) BOOL recording;
#end
You could use something like
#interface G4AppDelegate ()
#property (nonatomic, assign) BOOL recording;
#end
To make an "internal" property.
Or as the other answer states use an iVar in your implementation
Some books explain that you should only use getter and setter to access your ivar, even if they are private. This is a little too psychotique to me.
Before clang, u should have to create category on class and use synthesizer to make ur ivar private. like this:
#interface AppDelegate ()
#property(nonatomic, assign)int aValue;
#end
// + #implement AppDelegate
// #synthetise aValue;
that could be annoying since sometime u need some simple ivar, without any getter/setter control. And u're adding code where there is no need.
Now with clang you can put ur ivar directly on implementation file like this in ur code:
#interface AppDelegate (){
int _aValue;
}
#end
And u're hiding private ivar out of the scope the header.
Note, u can't compile this with gcc.

Properties vs. Instance Variables

I am confused as to why some classes declare a property but do not declare an ivar and vice versa.
Is it standard practice when declaring an instance variable to also declare it as a property as well?
Example:
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
is just standard practice when declaring a class's ivar to make it a property as well?
I get that the #property creates its own elongated setter (and getter with #synethesize) but why does it need to be an ivar as well?
It doesn't.
In the old days, ivars were required to be declared in the #interface. This is actually still true for PPC and i386 (i.e. 32-bit intel) targets. This is because of the fragile base class problem, which required that all subclasses know the exact size of their superclass. As such, ivars need to be in the #interface or nobody can subclass the class.
With the move to x86_64 and ARM, alongside obj-c 2.0 came a fix for the fragile base class problem. With this fix, class sizes no longer need to be known at compile time but can be deferred to runtime. Therefore, ivars can be declared in other places. Notably, an ivar can now be synthesized from a #property (more specifically the #synthesize line in the implementation). In Clang they can also be declared in a class extension block (which looks like #interface ClassName ()) or directly on the #implementation.
Today, there are 3 reasons why you find ivars declared in #interface blocks:
Old code (or programmers with old habits) that hasn't been updated to take advantage of the ability to hide ivar declarations.
Code that needs to run on PPC or i386.
Code that, for whatever reason, wants their ivars to be public. This should never be the case.
When writing code today that doesn't need to target the old runtime, you should either synthesize your ivars from your properties (preferred), or if you need ivars that aren't tied to properties you should declare them in a class extension or on your #implementation. The primary reason for this is because the header file documents the public API of your class and should not contain anything that's not public. Ivars are not public, and therefore should not be in the header file.

What is the difference between IBOutlet as a property or as a variable?

There are two different methods to declare IBOutlet.
In #interface section as variable:
IBOutlet UIButton *exampleButton;
Below the curve bracket but before #end of .h file as property:
#property (nonatomic, retain) IBOutlet UIButton *exampleButton;
What is the difference between these two methods and where should I use each one? Which method is better and in what cases?
Either one works fine in my experience. What doesn't work is declaring both the instance variable and the property "IBOutlet" -- that seems to really confuse things. If for some reason you want to avoid providing public access to your outlet, you can declare it as an instance variable and simply not create the property. On the other hand, now that the runtime will synthesize instance variables for you, many people are declaring only properties and skipping the explicit instance variable declaration; in that case, you'd obviously declare the property as the IBOutlet.
The #property combined with #synthesize setup the getter and setter methods for your objects. You should define it at least in the interface, and if you decide to create a property from it then you must also synthesize it the .m file.