When would a instance variable be used and when would a property be used?
In a header file such as this, when would an instance variable be used and when would a property be used?
Do they have to have the same name?
#import <开发者_高级运维;UIKit/UIKit.h>
@class BlueViewController;
@class YellowViewController;
@interface SwitchViewController : UIViewController {
YellowViewController *yellowViewController;
BlueViewController *blueViewController;
}
@property (retain, nonatomic) YellowViewController *yellowViewController;
@property (retain, nonatomic) BlueViewController *blueViewController;
@end
A @property
declaration simply creates accessor methods for an ivar. So properties don't really have names, only the accessor methods do; and these don't have to have the same name as the ivar. In fact, they don't even have to have a corresponding ivar.
You can change the names of the methods using the getter
and setter
decorators like this:
@property (assign, getter=isValid) BOOL valid;
Now, as I said, a @property
declaration simply creates accessor methods for an ivar. So you use properties when you want accessor methods. Here are a few reasons why you might want accessor methods:
Encapsulation (a property might be advertised as a different type than the ivar, or might not even have an ivar)
Related state changes (change another ivar or invoke a method when an ivar is modified)
You can use the
retain
decorator and@synthesize
the property to get much simpler memory managementYou can use
atomic
decorator (or simply not use thenonatomic
decorator, since properties are atomic by default) to create atomic properties
Here's an example to demonstrate points 1 and 2:
@interface Foo : NSObject {
@private
int flags;
// Humpty and Dumpty are mutually exclusive
BOOL humpty;
BOOL dumpty;
}
@property (nonatomic) BOOL flagA;
@property (nonatomic) BOOL flagB;
@property (nonatomic) BOOL humpty;
@property (nonatomic) BOOL dumpty;
@property (nonatomic, readonly, getter=isClean) BOOL clean;
@end
@implementation Foo
@synthesize humpty, dumpty; // Synthesize the getters, but provide the setters
- (void)setHumpty:(BOOL)value {
if(value && dumpty)
dumpty = NO;
humpty = value;
}
- (void)setDumpty:(BOOL)value {
if(value && humpty)
humpty = NO;
dumpty = value;
}
- (BOOL)flagA {
return flags & 0x01;
}
- (void)setFlagA:(BOOL)value {
if(value)
flags |= 0x01;
else
flags &= ~0x01;
}
- (BOOL)flagB {
return flags & 0x02;
}
- (void)setFlagB:(BOOL)value {
if(value)
flags |= 0x02;
else
flags &= ~0x02;
}
// Making this a property doesn't really make sense
// but I'm just trying to demonstrate what you can do
// with properties
- (BOOL)isClean {
return flags == 0;
}
@end
You want to use the properties for all your external access to provide encapsulation, it's up to you whether you want to use them internally though, i think it's a matter of taste.
By using the properties from outside of your class you can for example do some lazy loading and it becomes a lot easier to make any potential API changes by providing deprecation warnings in the getters/setters.
They can have the same name, although they don't have to. Indeed, it's not required for the externally-visible property to correspond exactly to a single instance variable at all. Such a correspondence is expected if you're going to @synthesize
the accessor methods, but there are quite legitimate reasons for creating the methods manually and making them do something other than just getting/setting a matching ivar.
Instance variables are normally not accessible from the outside world, so all external access has to be via the property methods. (It is possible to declare ivars @public
, but this is rarely a good idea.)
From within the object, whether you access as properties or instance variables depends on what the properties actually are and what you're doing with them.
For simple synthesized properties it is common to use the accessors (either explicitly using [self setXxx]
or using the dot notation as self.xxx
) except within dealloc
(and possibly init
, depending on who you ask).
In more complex cases, you really have to think about what it is you are trying to achieve. But if you've gone to the trouble of making them properties you probably want whatever functionality is encapsulated in the accessor methods to be called most of the time.
At any rate, read the properties documentation to get a better understanding of what's going on.
精彩评论