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

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.

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 is the difference between these three ways to declare a variable?

I am learning Objective-C and was just curious. I can create an object of a NSString in these places, and please provide any others. To me they all do the same thing. I don't know what is the difference is between them. Where is it stored? From where can I access it? What are the advantages?
1)
// .h
#interface ...
#property (strong,nonatomic) NSString *text;
#end
2)
// .h
#interface ... {
NSString *text
}
#end
3)
// .m
#interface ... ()
#property (strong,nonatomic) NSString *text;
#end
First and foremost, my answer is based on the latest Clang compiler, older versions worked slightly different.
So, you're not creating an object in neither. You're not even declaring an object in two of them.
In the first case, you're actually telling the compiler that you need to expose a property called text of type NSString. What the compiler does, is declaring an instance variable for you _text (which you can access without a problem by the way) and the methods needed to get and set that instance variable. As you can see the storage is still internal, you just have getters and setters set for you.
In the second case you're actually declaring an instance variable (ivar) yourself, just as the compiler does with _text. It's accustom to prefix it with _. The storage is still internal. On top of that, you can't access your ivar from outside, since it has no getter or setter and the implicit declaration is #private.
In the third case, you create an anonymous category (thus the empty parentheses) which adds a property to your class. Storage for this is a little bit harder/longer to explain, if you are curious about it, you can search up the Apple docs, see what a category is and so on. You can only access your property from within your class in this case, which makes it somehow redundant (the getters and setters), you could have declared it as an ivar.
You can also declare your ivars like this:
#interface GenericViewController : UIViewController{
NSString * text;
}
#end
#implementation GenericViewController{
NSString * text;
}
#end
Both of the above have local storage and private visibility (can't be accessed from outside). The difference between the two is that instance variables declared in the implementation are implicitly hidden and the visibility cannot be changed with #public, #protected and #private. If you use those directives you won't get compiler errors but are ignored.

#synthesize ivarName = _ivarName convention, preference or performance? [duplicate]

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.

public objects and use of property

I'm a bit confused; if an object is declared in the .h file it is considered automatically as "public" right? We use a #property in the .h file, however, to edit them? This is where I don't understand: we use the getter/setter for private objects, so why do we use the #property for objects declared in the .h file and thus considered as "public"?
Second thing, I found this example: I don't understand why we use a #synthesize for primaryKey in this code: http://staging.icodeblog.com/wp-content/uploads/2008/08/9-todom1.png
and why we don't use a #property for the database object?
It is not correct that if an object (ivar) is declared in a .h file, then it is public. It is only if getter/setter methods are provided, otherwise it is not.
Indeed, the #property/#synthesize directives are facilities meant to declare and define default getter/setter methods. So, instead of writing them yourself, you just use the directives.
It is also worth noting that declaring properties you get the possibility of using the dot notation to refer properties of your objects. And also that they clarify a lot, thanks to the retain/assign/copy specifiers, how memory is meant to be managed for that properties. (And, of course, #synthesize will just do that correctly for you).
About your sample, in fact, whether an ivar is associated to a property or not is a design choice. Possibly, you just reconsider the assumption that ivars declared in .h files are public by defaults, and it will become clearer. In other words: primaryKey is public, database is not.
A very nice tutorial can be found here but also do not forget Apple docs.
EDIT:
about your question from the comment section:
it is not necessary that every ivar has a property, nor that it has getter/setter in order to be used inside of that class implementation.
#interface SomeClass : NSObject {
AnotherClass* _anotherClassObj;
AThirdClass* _aThirdClassObj;
}
#property (nonatomic, retain) AnotherClass* anotherClassObj;
#end
So, here you have two ivars; only one has got a #property declaration. In your .m file you may have, e.g.
#implementation SomeClass;
#synthesize anotherClassObj = _anotherClassObj;
- (void)initWithClasses:(AnotherClass*)obj1 and:(AThirdClass*)obj2 {
.....
self.anotherClassObj = obj1;
_aThirdClassObj = obj2;
...
}
....
#end
In this code:
#synthesize will provide implementation for getter/setter for anotherClassObj so you can use syntax: self.anotherClassObj = obj1; that syntax can be used equally from inside and outside the class implementation;
when you have no getter/setter (either auto-generated or custom) you can assign directly to an ivar by using the syntax _aThirdClassObj = obj2;, with the semantics of simple pointer copy; anyway, _aThirdClassObj will not accessible from outside that class;
furthermore, #property ... anotherClassObj notwithstanding, you can still refer _anotherClassObj directly in your .m file, like in _anotherClassObj = xxx, bypassing getter/setter, if you ever need it.
One thing you should have clear is that getter/setter are not only a way to make an ivar "public". They also play an important role in managing the retain count (depending on which specifier you choose among retain/assign/copy in the property declaration). So, in self.anotherClassObj = obj1; above, obj1 is assigned to _anotherClassObj and it is also retained (and if _anotherClassObj was previously pointing to an object, that object will be sent a release). Raw ivar assignment does not provide that kind of facility.
In my opinion, the retain count management feature of properties is far more important than visibility for deciding whether I use a property or not.
Not everything in the header is public, by default ivars (items in the { }) are #protected. The purpose of the #property is data encapsulation. #synthesize or #dynamic is used for declaring the way you want to implement your property and one or the other is necessary to prevent crashes and warnings.
Resources:
Defining Classes #protected, #package, #private, #public reference
Declared Properties #property reference

Since when is it possible to declare Objective-C 2.0 properties in a category?

I always thought that one cannot declare an object property in a category.
Until my partner did it in our app's code, and it seemed to work.
I went on a SO and Google binge to try to explain to him that no, Objective-C categories can only be used to add methods, not properties. I found questions such as:
Setting New Property In Category Interface Implementation (look at the accepted answer)
Can I add a property for a method not in my category?
But then I found this link on Apple's site that contains the following about the #property declaration:
A property declaration begins with the
keyword #property. #property can
appear anywhere in the method
declaration list found in the
#interface of a class. #property can
also appear in the declaration of a
protocol or category. (emphasis added)
I know that this doesn't work:
#interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
#end
But this compiles:
#interface MyClass ()
#property NSInteger foobar;
- (void) someCategorizedMethod;
#end
My question is (a) what's the best practice here? and (b) is this something that is new to Objective-C 2.0, and instead of using a "real" iVar, it simply uses associative storage behind the scenes to make this work?
You have always been able to declare an #property in a category. What you couldn't do -- and still can't -- is declare storage for the property in the category, neither as an instance variable nor via `#synthesize.
However....
#interface MyClass () is not a category. It is a class extension and has a distinctly more specific role than a category.
Namely, a class extension can be used to extend a class's #interface, and this includes #properties that can be #synthesized (including synthesizing storage in the modern runtime).
Foo.h:
#interface Foo
#end
Foo.m:
#interface Foo()
#property int x;
#end
#implementation Foo
#synthesize x; // synthesizes methods & storage
#end
it simply uses associative storage
behind the scenes to make this work?
Nope -- it is a real instance variable. The modern runtime fixes the fragile base class problem.
#interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
#end
The above doesn't work (as expected) because foobar is, effectively, a global variable.
If you change it to:
#interface MyClass () {
NSInteger foobar;
}
- (void) someCategorizedMethod;
#end
Then it'll work with the latest release of the llvm compiler (with the right flags, as #Joshua indicated in a comment).
Generally speaking, properties are nothing different from other methods. As long as the ivar used is available in the ordinary class, there is no problem at all. It's just syntactic sugar.
Things start to get more difficult if also the ivar is automatically created, as is possible in some configurations.
The main point here is that declaration of the ivar is independent from the property.
Assotiative storage is the solution.
Have a look at this post.