concept of instance properties - objective-c

would you please break my confusion.
If I define a property in a class
#interface Class
{
UIScrollView * _scrollView;
}
#property (nonatomic, retain) IBOutlet UIScrollView * scrollView;
#end
#implement
#synthesize scrollView = _scrollView;
#end
When I wanna implement it, I can use
_scrollView.contentSize = xxx
or
self.scrollView.contentSize = xxx
What's the difference between the two description?
Thanks for your answering...

The direct reference to the instance variable is precisely that -- a reference to a field in the instance, unaffected by the fact that it's also the "backing store" of a property.
The self.propName reference, on the other hand, is shorthand for either [self propName] (if reading) or [self setPropName:newPropValue] (if setting). Ie, those references go through accessor methods. This isn't real important if the property is defined as assign, but if it's retain then the setter method takes care of all the retain logic.
Further, you can implement your own property accessors -- -(SomeType*) propName {...} and -(void) setPropName:(SomeType*)propParm {...} -- if you want to have them do something special, such as "lazy" initialization.
(Also, properties default to "public" access, while instance variables default to "private" access.)

Related

Is it bad practice to set a property to be nonatomic instead of synthesizing the ivar

I learned today that when writing your own getter/setter methods, ivars aren't automatically synthesized in the getter:
property not working with getter AND setter
To get around this, I just set my property to be nonatomic and then only wrote the setter-- which allowed me to avoid writing #synthesize property = _property
I know the main purpose for nonatomic properties is so the system can read/write the property faster because it doesn't concern itself with locking the property while writing
But as a side-effect (as it seems), you don't have to write both a setter and getter.
Is this bad? I'm just not sure if there are other drawbacks I'm not seeing
EDIT: Adding code for clarity:
Implementation:
#interface GalleryManager ()
{
NSObject<GalleryManagerDelegateProtocol>* _delegate;
}
...
-(NSObject<GalleryManagerDelegateProtocol>*)delegate
{
return _delegate;
}
-(void)setDelegate:(NSObject<GalleryManagerDelegateProtocol> *)delegate
{
[self stopObservingDelegate];
_delegate = delegate;
[self startObservingDelegate];
if ( delegate && self.didWakeFromNib )
{
[self setupDefaults];
[self readGalleryFromDisk];
}
}
Header:
#property (weak, nonatomic) NSObject<GalleryManagerDelegateProtocol> *delegate;
I wanted to remove the instance variable defined in the extension (_delegate), for no reason other than I didn't think it was necessary
But by doing so, the -delegate getter method broke, unable to recognize _delegate. Because I had the #property in the header, I thought the _delegate ivar would be automatically synthesized, but as I have found it is only recognized in the setter.
So in that SO question I linked at the beginning, the answer was to add #synthesize delegate = delegate at the beginning of the implementation
But instead I wanted to just change the #property in the header to be nonatomic, and then just straight up delete the -delegate getter method
Again, for no other reason than to be as clean as possible

use of #property and #synthesise?

I was wondering what the point of #property and #synthesise were. At the moment I use the following to declare something:
//Class.m
#import "Class.h"
CCNode *node;
#implementation
//init, etc..
But I have seen others use:
#property (nonatomic, etc..) CCNode* node;
#synthesise (nonatomic, etc..) node;
//I am not too sure on how this type of declaration works, please correct me on how it's done.
They both seem to work in the same way, what are the advantages of the #property and #synthesise way? Do they do different things, if so, what?
#property and #synthesize are two objective C keyword that allow you to easily create your properties and therefore avoid to write by hand getters and setters methods of the property.
The #property define the property itself, should be placed in the header file and can get some attributes (as for example : strong, nonatomic, retain assign, copy), the #synthesize should be placed into the implementation file and tell the compiler to generate the body of getter and setter method.
These two keyword are extremely useful when coupled with the right use of their attributes, because they take care of the generation of the property code and most of all they take care of the memory management of the property.
#property - create the declaration of your getter and setter.
#synthesize - provide the definition of getter and setter based upon the parameters which are passed inside property.
Check this out, there are a lot more details about the same present there - https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
on using #property the compiler will take care of declaring getter and setter methods based on readonly and readwrite
readonly -> getterMethod
readwrite -> both setter and getter method
on using #synthesize the compiler will take care of defining getter and setter methods
If you have an instance variable (ivar) in your class, you can't access it from other classes usually. So you have to make public accessor methods (getters and setters). They look something like this:
Setter:
- (void)setMyVariable:(SomeClass *)newValue {
if (newValue != myVariable) {
[myVariable release];
myVariable = [newValue retain];
}
}
Getter:
- (SomeClass *)myVariable {
return myVariable;
}
This was the way you had to do it before Objective-C 2.0. Now you can use #property and #synthesize to speed this up. It's basically just a shortcut.
In the header you use #property to define what kind of setters you want. Should the setter retain the passed value (like in my example) or copy or just assign?
And in the implementation you just write #synthesize to make the compiler include the automatically created getters and setters at that position. Usually at the top of your implementation.
My feeling is that all iVars should have an associated underscore synthesised property (using an _iVar prevents accidental direct access), and all access to the iVars, apart from init and dealloc methods, should via the property.
IMHO the big win is memory management - it's safer and much easier as there is no need to remember which iVars have been retained.
And think of how much work is required to code an accessor - 4 lines for getter and 2 for a setter.
At some point in the future #synthesize is likely to be optional, so all you'll need is the #property.

Declaring class attributes Objective-C

I'm starting to learn Objective-C and I have a question:
When you declare the properties of a class, what is the difference between doing this?
FIRST CASE:
#interface ViewController : UIViewController
{
UILabel *label;
}
#property(nonatomic,retain) UILabel *label;
#end
SECOND CASE:
#interface ViewController : UIViewController
{
}
#property(nonatomic,retain) UILabel *label;
#end
In the first case, I'm declaring a class with one attribute (UILabel *label) and later, I'm declaring the properties for that label.
In the second case, I only declare the properties.
I always thought I should declare class attributes.
In the fist case, i'm declaring a class with one atribute (UILabel *label) and later, i'm declaring the properties for that label.
No you are not. In the first case, you are declaring an instance variable called label and a pair of accessor methoods called -setLabel: and -label (known together as a property). You have established no link between the property and the instance variable. They are at this point independent entities.
If you do this in the implementation:
#synthesize label = fooBar;
You are saying that the methods of the label property actually use a completely different instance variable to back the property.
I always thought I should declare class attributes
I used to think the same, but actually, if you are synthesizing the property, there's no point in declaring an ivar separately because the #synthesize will do it for you (and in ARC will apply the correct ownership qualifiers). I now do something like this:
#synthesize label = label_;
so I don't use the instance variable when I mean to use the property. e.g. [label length] flags an error when I meant [[self label] length]
Also, if you change the implementation of the property to not use an instance variable, if you haven't declared the instance variable explicitly, it will go away and accidental uses of it (+ those in init and dealloc) will be flagged as errors.
Another difference that has not been mentioned:
In your first case, label has protected access. Instance variables are by default #protected if not declared otherwise.
On the other hand, in the second case, label is private (at least in my compiler).
This difference matters when you have subclasses.

Why do I declare a #property when I can use an inline variable instead?

I have spent a few days learning Objective-C and have a few questions about #property. I have experience with C# so understand the need for pointers, initialization etc.
So as an example:
#interface MyClass : NSObject
{
IBOutlet UIImageView *image;
}
#property (retain, nonatomic) UIImageView *image
#end
#implementation MyClass
#synthesise image
#end
I understand that #synthesise is used to create the #property. But I have a few questions just to help me clear things up:
Does the #property duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
Does #synthesise remove my need to use image = [[UIImageView alloc] init]?
If I do not provide a #property and still go ahead creating and destroying my variable manually, does that make any difference?
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.
Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The ivar declaration of image is redundant when using the most recent compiler releases.
The former declares an ivar (type + name + instance storage).
The property declaration specifies the type, name, storage (in more recent compiler releases), declares the accessor methods (e.g. - (UIImageView *)image; and - (void)setImage:(UIImageView *)pImage;), and other property specifiers (which are used when the accessors are generated by the compiler).
Does #synthesise remove my need to use image = [UIImageView alloc]?
No. You still need to implement your initializer and dealloc (in MRC) appropriately.
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
That would be fine, when you do not want/need boilerplate accessor methods generated for you. It's a design choice. Not every ivar needs accessor methods.
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.
The biggest reason they exist is convenience. Properties save a lot of boilerplate code.
There is no more flexibility with properties -- properties implement the most practical uses.
It's infrequent that atomicity (in this context) is equivalent to proper thread safety and correct concurrent execution.
1) The property does not replace the class member. A property is a declaration that you want the accessors (getter and setter) for a class member to perform certain "automatic" tasks and have a certain name.
For example:
#interface MyClass : NSObject
{
NSInteger __myInt;
}
#property (assign) NSInteger myInt;
#end
#implementation MyClass
#synthesize myInt=__myInt;
#end
The above code, for all intents and purposes, is causing the following methods to be automatically generated at compile time:
-(NSInteger) myInt
{
return self->__myInt;
}
-(void) setmyInt:(NSInteger)val_
{
self->__myInt = val_;
}
Of course, what happens "in the background" when Xcode compiles your program is a bit different and more nuanced, but this is basically what happens.
2) I'm not entirely clear what you mean by this one... You always need to alloc and init your variables, regardless of accessor synthesis.
3) No. Properties/synthesis are only needed for a) convenience, be it syntactic or atomicity for multithreading, and b) external access to members inside your class.
EDIT:
To clarify on multithreading and properties, declaring a property nonatomic does a great deal for thread safety. This, and my response to #3, addresses your last concern in your question.
You can do this:
#interface MyClass : NSObject
#property (retain, nonatomic) IBOutlet UIImageView *image;
#end
#implementation MyClass
#synthesize image;
#end
Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The property adds things on-top of the ivar like KVO and thread safety if it's atomic.
Does #synthesise remove my need to use image = [UIImageView alloc]?
No
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
If you don't make a property you lose out on the things a property gets you like KVO, it's a judgment and api call on how the variable will be used. Under arc it is much easier to use straight up ivars because you don't have to replicate the retaining and releasing the property did automatically.
The 'image' in #property (retain, nonatomic) UIImageView *image line is just a name of the property and IBOutlet UIImageView *image; is an ivar which you access through self.image. I always name an ivar for property the same as the name but add _ :
UIImage * image_;
#property (retain, nonatomic) UIImageView *image;
#synthesize image = image_;
If you will not create an ivar for your property the Xcode do it automatically for you (the name of the ivar will be the same as the name of property)

Differentiate between iVar and Method Parameter?

I have a property like this:
#property (nonatomic, strong) IBOutlet UIImageView *backgroundImageHolder;
I want to adjust the setter, and XCode fills out the method signature like this:
-(void)setBackgroundImageHolder:(UIImageView *)backgroundImageHolder {
However, to actually do anything in the method, I must change the parameter backgroundImageHolder to something like backgroundImageHolderIn. Is there any way to avoid this? Is there any way to set the iVar without reinvoking the setter (causing an endless loop), or just referring to the parameter again?
I just tried:
self->backgroundImageHolder = backgroundImageHolder;
but the compiler warns me anyway.
Note: I am using the automagically generated iVar that the compiler makes for the property, but by default its name is the same.
You can give tell the compiler how to name the generated ivar:
#synthesize propertyName = iVarName;
If there actually exists an ivar named iVarName that one is used. If it doesn't exist the compiler creates it for you.
Like:
#synthesize backgroundImageHolder = myBackgroundImageHolder;
Now you can access the instance variable myBackgroundImageHolder. You don't need to declare it in the interface first.
Well, the conflicting parameter name seems to be pretty well covered by now. Basically, you have to either:
Rename the incoming argument
Rename the synthesized iVar
Once you have a method argument that differs from the iVar you're attempting to set, you have everything you need to write a custom setter. To avoid the infinite loop, you have to not call the setter you're currently implementing, whether it be via dot syntax or method brace syntax. Instead, refer directly to the backing iVar. You'll need to take care to manually implement the memory management semantics you declared in the property though (assign vs. retain, etc.):
// Backed by _myProperty iVar.
- (void)setMyProperty:(NSInteger)myProperty {
// Insert custom code here...
[self setMyProperty:myProperty]; // Obviously bad.
self.myProperty = myProperty; // Less obviously bad (thanks dot syntax)
// but semantically identical to the previous line.
_myProperty = myProperty // Good, (assuming assign semantics).
}
Compiler warns you because when you declare #property it creates instance variable with exact same name as a property (and as a parameter of a setter method). One way to avoid it is to create differently named instance variable and then pair it with property using #synthesize like this:
// .h
#interface Foo : NSObject {
IBOutlet UIImageView *myfooImageView;
}
#property (nonatomic, retain) UIImageView *publicFooImageView;
// .m
#implementation Foo
#synthesize publicFooImageView=myfooImageView;
#end
The clearest thing to do would be this:
In your header, define an iVar for backgroundImageHolder like so
#interface Something : NSObject
{
IBOutlet UIImageView *_backgroundImageHolder
}
Notice the leading underscore.
Then in your .m file, use either the synthesize call like so:
#synthesize backgroundImageHolder=_backgroundImageHolder;
or just define the getter and setter methods yourself: Then you are able to access the ivar via "_backgroundImageHolder" without any danger of accidentally calling the setter again.