Reputation: 3619
Suppose I have a property called myPropertyName
defined in my class MyClassName
. Manual memory management is used throughout this post.
MyClassName.h
#import <UIKit/UIKit.h>
@interface MyClassName : NSObject {
@private
NSObject* myPropertyName;
@public
}
@property (nonatomic, retain) NSObject* myPropertyName;
// Some methods prototypes are here
@end
MyClassName.m
#import "MyClassName.h"
@implementation MyClassName
@synthesize myPropertyName;
// Some methods are here
@end
I'm confused with usages such as the place of myPropertyName
declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized -(void)init
method for my class myClassName
.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
This one is calling myPropertyName
setter, but I'm not sure what is the name of the instance variable being used in the setter, myPropertyName
(since I've declared a @private field named myPropertyName
) or _myPropertyName
(people say that this one with underbar is the default)?
myPropertyName = [[NSObject alloc] init];
Does this initialize the instance variable of the myPropertyName
property? If I don't have @synthesize myPropertyName = _myPropertyName;
, would it be wrong since the default instance variable for the property is said to be _myPropertyName
.
_myPropertyName = [[NSObject alloc] init];
Is _myPropertyName
still declared as the instance variable for my property myPropertyName
even if I use @synthesize myPropertyName;
and @private NSObject* myPropertyName;
?
In my understanding, a property is just a name (such as myPropertyName
), there should be some instance variable encapsulated to be used in actual operations in the code, such as assigning values.
Upvotes: 0
Views: 122
Reputation: 11211
First off, I highly recommend reading Apple's documentation on properties, also linked by nhgrif. However, I understand docs can be a bit dense reading material (though Apple's, I find, are not so bad), so I'll give a brief overview of properties here.
I like examples, so I'm going to rewrite your two classes in a bit more current form.
MyClassName.h
#import <UIKit/UIKit.h>
@interface MyClassName : NSObject
@property (nonatomic, strong) NSObject *myPropertyName;
// method prototypes here
@end
MyClassName.m
#import "MyClassName.h"
@implementation MyClassName
// some methods here
@end
The class MyClassName
now has a property called myPropertyName
of type NSObject *
. The compiler will do a lot of work for you for "free" in this instance. Specifically, it will generate a backing variable, and also generate a setter and getter for myPropertyName
. If I were to rewrite the two files, and pretend I'm the compiler, including that stuff, they would look like this:
MyClassName.h
#import <UIKit/UIKit.h>
@interface MyClassName : NSObject {
NSObject *_myPropertyName;
}
@property (nonatomic, strong) NSObject *myPropertyName;
- (void)setMyPropertyName:(NSObject *)obj;
- (NSObject *)myPropertyName;
@end
MyClassName.m
#import "MyClassName.h"
@implementation MyClassName
- (void)setMyPropertyName:(NSObject *)obj
{
_myPropertyName = obj;
}
- (NSObject *)myPropertyName
{
return _myPropertyName;
}
@end
Again, all of this is happening for "free": I'm just showing you what's happening under the hood. Now for your numbered questions.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
First of all, you should probably be using Automatic Reference Counting, or ARC. If you are, you won't be allowed to call autorelease
. Ignoring that part, this works fine. Excluding the autorelease
, this is exactly equivalent to:
[self setMyPropertyName:[[NSObject alloc] init]];
Which, if you look at the second .m
file I wrote out, above, will basically translate to:
`_myPropertyName = [[NSObject alloc] init];
myPropertyName = [[NSObject alloc] init];
As written, this code will give a compiler error, since there is no variable called myPropertyName
in this class. If you really want to access the instance variable underlying (or, "backing") the myPropertyName
property, you can, by using its real name:
_myPropertyName = [[NSObject alloc] init]; // note the underscore
But most of the time, it's better to use the setter, as in point 1., since that allows for side effects, and for Key-Value Coding, and other good stuff.
_myPropertyName = [[NSObject alloc] init];
Oh. Well you got it. See point 2.
You mentioned that:
I'm confused with usages such as the place of
myPropertyName
declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized-(void)init
method for my classmyClassName
.
In case it hasn't been made clear, a property is something of an abstract concept; its data is stored in a normal instance variable, typically assigned by the compiler. Its access should usually be restricted to the setter and getter, with important exceptions. To keep this answer short, I won't go into more detail than that.
One more thing: as nhgrif mentioned, you don't need to use the @synthesize
keyword anymore. That is implicitly understood by the compiler now.
If you're not sure about any of this, post a comment or, better yet, read the docs.
Upvotes: 2
Reputation: 62052
Let's take this example:
@property NSString *fullName;
If in the implementation, we override the setters and getters, and in these setters and getters, we don't use an instance variable fullName
, it is never created. For example:
- (NSString *)fullName
{
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
- (void)setFullName:(NSString *)fullName
{
//logic to split fullName into two strings
//self.firstName = etc
//self.lastName = etc.
}
In this example, there is no instance variable for fullName
created.
This is according to Apple's Official Documentation
If, however, you don't override both the setter and getter, an instance variable is created.
As a sidenote, you can declare a property readonly
, and then simply overriding the getter
(without using the variable) will prevent an ivar
being created. Likewise, you can declare a property writeonly
and just override the setter
.
Upvotes: 1