在诸如此类的头文件中,何时使用实例变量以及何时使用属性?
他们必须具有相同的名称吗?
#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
答案 0 :(得分:4)
@property
声明只为ivar创建存取方法。所以属性实际上没有名称,只有访问器方法呢;这些不必与ivar同名。事实上,他们甚至不需要相应的伊娃。
您可以使用getter
和setter
装饰器更改方法的名称,如下所示:
@property (assign, getter=isValid) BOOL valid;
现在,正如我所说,@property
声明只是为ivar创建存取方法。因此,当您需要访问器方法时,可以使用属性。以下是您可能需要访问器方法的几个原因:
封装(属性可能会宣传为与ivar不同的类型,或者甚至可能没有ivar)
相关状态更改(更改另一个ivar或在修改ivar时调用方法)
您可以使用retain
装饰器和@synthesize
属性来简化内存管理
你可以使用atomic
装饰器(或者根本不使用nonatomic
装饰器,因为默认情况下属性是原子的)来创建原子属性
以下是演示第1点和第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
答案 1 :(得分:0)
它们可以具有相同的名称,尽管它们不必具有相同的名称。实际上,外部可见属性并不需要完全对应于单个实例变量。如果您要使用@synthesize
访问器方法,那么这种对应是,但是有充分合理的理由手动创建方法并让它们做除了获取/设置之外的其他方法匹配ivar。
实例变量通常无法从外部访问,因此所有外部访问都必须通过属性方法。 (可以声明ivars @public
,但这不是一个好主意。)
从对象内部,无论您是作为属性还是实例变量进行访问,都取决于属性的实际内容以及您使用它们执行的操作。
对于简单的合成属性,通常使用访问器(明确使用[self setXxx]
或使用点符号作为self.xxx
),dealloc
内部(可能init
除外) ,取决于你问的是谁。
在更复杂的情况下,你真的必须考虑你想要实现的目标。但是,如果你遇到了制作属性的麻烦,你可能希望在大多数情况下都可以调用封装在accessor方法中的任何功能。
无论如何,请阅读properties documentation以更好地了解正在发生的事情。
答案 2 :(得分:0)
您希望使用所有外部访问权限的属性来提供encapsulation,这取决于您是否要在内部使用它们,我认为这是一个品味问题。
通过使用类外部的属性,您可以执行一些惰性loading,通过在getter / setter中提供弃用警告,可以更轻松地进行任何潜在的API更改。