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.
Related
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.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Synthesized property and variable with underscore prefix: what does this mean?
The usage of Objective-C properties has always felt awkward to me. It's one of the "I know how to use them, but I'm not always sure why I'm using them." kind of things and recently I've been seeing a lot of this:
// in .h file
#interface MyObject : NSObject
{
id _coolIvar;
}
#property (assign) id coolIvar;
#end
// in .m file
#implementation
#synthesize coolIvar = _coolIvar;// <- whats the point of that.
#end
So what is the point of declaring an ivar with an underscore and then using #synthesize to access it, Opposed to just declaring the #property with the same name as the ivar?
Side Question:
I've noticed that this convention has been becoming increasingly more popular since blocks started becoming the preferred approach for async callbacks opposed to the target/selector approach. Is that a coincidence or does the above #property declaration convention play nicer with block scopes?
It's preference.
It's also my preference to not declare the variables twice and just let them be synthesized like:
// in .h file
#interface MyObject : NSObject
#property (assign) id coolIvar;
#end
// in .m file
#implementation
#synthesize coolIvar = _coolIvar;
#end
The two reasons I like to use the _ prefix is
I know when I am going through an accessor and when I am accessing the variable straight.
If it makes sense for me to call an ivar address it is more than likely that inside a method a similar variable would also be logically called address. If my ivar does not have an _ prefix then my local address will mask the ivar address.
I also like how xcode will autocomplete vaiables starting with an _ when you start typing your #synthesize myVar = _...
NB
You may run into the odd name clash (I have only once) but the warning that the complier gives you makes it a pretty easy spot and simply changing the name is a quick win.
#isaac touched on not declaring ivars so that they are not publicly advertised but does not explain how/why. Basically you can declare #property's in a class extension to still give you the benefits of the #synthesized getter/setter but without making your public API look ugly.
Your previous example would look like this (if you wanted coolIvar to not be publicaly advertised):
// in .h file
#interface MyObject : NSObject
#end
// in .m file
#interface MyObject () <-- Like a category but with no name
#property (assign) id coolIvar;
#end
#implementation
#synthesize coolIvar = _coolIvar;
#end
I use the _ivar construct to make sure that I don't access the ivar directly (by mistake) when I really intend to go through the accessors.
With the modern runtime (iPhone applications and 64-bit programs on Mac OS X v10.5 and later) the ivar declaration is no longer required. So your code is reduced to:
// in .h file
#interface MyObject : NSObject
#property (assign) id coolIvar;
#end
// in .m file
#implementation
#synthesize coolIvar = _coolIvar;
#end
Per #Monolo's answer, the _ivar is a good failsafe to make sure you don't inadvertently access the ivar directly. Remember, the #property and #synthesize is there to replace boilerplate code - without it you'd have to code getter and setter accessors.
There are a couple benefits to differentiating ivars from property accessors.
One is described by Monolo - it prevents mistakingly accessing an ivar when what you intended to access was a property.
Another is that in theory it guards against collisions - cases where you might name an ivar identically to another ivar that's beyond your implementation (ie, a superclass ivar name).
There are different thoughts on best practices, but lately I've read in several places I consider reliable that the best practice is actually to no longer to declare ivars at all in your interfaces (ivars are created implicitly via the property declaration).
Some people don't like "implicit" - but there are material benefits: Not declaring them avoids advertising ivars that aren't really public. It also goes even further in avoiding collisions - because in theory when a property is synthesized and the ivar generated, it will do so without introducing a convention that may itself collide with a private ivar naming convention (as may be the case with preceding or trailing underscore).
Preference. Some people like to prefix instance variables with a underscore (so one can easily tell if one is referencing a ivar, or a variable in a more local scope), and some don't.
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.
sorry If am I being too picky on this one but I am learning iOS programming now and I've seem some people who declare the IBOutlet like this:
IBOutlet attached to property
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface CustomTableViewController : UITableViewController {
CustomCell *customCell;
}
#property (nonatomic, retain) IBOutlet CustomCell *customCell;
#end
And some declaring like this:
IBOutlet attached to the declaration inside the interface
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface CustomTableViewController : UITableViewController {
IBOutlet CustomCell *customCell;
}
#property (nonatomic, retain) CustomCell *customCell;
#end
which one is the proper way to declare it? Are any differences between them?
If someone know to explain why do they put it on different places it would be awesome to learn.
Thanks a lot :)
Both of those are still "inside the interface" so your title it a bit confusing but I see what you are asking.
In many cases the result of either approach will be the same but they are different. An IBOutlet property will call the property's setter method which gives you an opportunity to override that setter if setting that property should have some side effect.
I prefer to use outlets on properties because I think it makes the memory management of the objects loaded from the nib much clearer. Take a look at memory management of nib objects and I think you will see what I mean.
Objects in the nib file are created with a retain count of 1 and then autoreleased. As it rebuilds the object hierarchy, UIKit reestablishes connections between the objects using setValue:forKey:, which uses the available setter method or retains the object by default if no setter method is available. This means that (assuming you follow the pattern shown in “Outlets”) any object for which you have an outlet remains valid. If there are any top-level objects you do not store in outlets, however, you must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.
IBOutlet ivars will call setters for those ivars if they exists and directly retain the object loaded from the nib if no setter is found.
Advertising the property as the IBOutlet at least makes it clear that the property's setter will always be used and follow whatever memory management rule has been set for that property.
Finally I argue that IBOutlets are part of the public interface of a class and it is therefore better to expose methods (via a property) for working with them eager than using -setValue:forKey: to manipulate the backing ivars which should be an implementation detail.
The two styles are interchangeable, there is no difference in the generated code or the way objects will be loaded from a nib. Really.
However, both styles have a redundant line. Simply leave out the ivar declaration. Just the line
#property (nonatomic, retain) IBOutlet CustomCell *customCell;
is sufficient in the modern runtime.
If you have a complex project, I suggest moving all the outlets out of the public interface into a separate header file. Most outlets are private interface, the only reason to have them in a header is so Interface Builder can find them.
You can declare both ways, there is no difference actually.
But, here is the thing:
If you need your class to have some ivar with a special behavior or it has to be accessed from outside, etc, and it has to be a property, then I will say you have 2 options to choose from (attached to the property and inside the class interface).
If that is not your case, don't create a property, is not necessary, just do it inside your class interface.
Hope it helps ;)