在UIView子类中,我有这个属性:
@property (nonatomic) CGFloat scale;
#define DEFAULT_SCALE 0.90
这个getter和setter:
-(CGFloat)scale
{
if (!self.scale) {
return DEFAULT_SCALE;
}else{
return self.scale;
}
}
-(void)setScale:(CGFloat)scale
{
if (scale != self.scale) {
self.scale = scale;
[self setNeedsDisplay];
}
}
这是不正确的,因为例如在getter中检查self.scale会导致无限循环。编写getter和setter的正确方法是什么,这样我就不会得到无限循环?
答案 0 :(得分:15)
您应该可以_scale
直接访问ivar。你的getter / setter看起来像是:
更新:正如@ wattson12在下面的评论中指出的那样,您需要在实施中添加@synthesize
。
@synthesize scale = _scale;
-(CGFloat)scale
{
if (!_scale) {
return DEFAULT_SCALE;
}else{
return _scale;
}
}
-(void)setScale:(CGFloat)scale
{
if (scale != _scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
答案 1 :(得分:1)
Dot notation can be a tad misleading at first.
在你发布的这一行中
self.scale = scale;
您没有分配给本地变量。实际上,您正在向-setScale:
发送消息self
。这一行相当于
[self setScale:scale];
由于您从-setScale:
内部呼叫-setScale:
,因此您将获得此无限递归。
您需要做的是在setter中设置一个实例变量(而不是从内部调用您的setter)。通常,只需写下
@property (nonatomic) CGFloat scale;
您已经创建了一个实例变量_scale
。 但,因为您还覆盖了-scale
和-setScale:
,因此不会创建此实例变量。因此,您需要自己添加实例变量。在您的课程'声明@interface
中(或者class extension @interface
)
//If adding the instance variable to the class declaration:
@interface MyClass : Superclass
{
//....
CGFloat _scale;
}
//....
@end
完成此操作后,将线路更改为
就足够了_scale = scale;
您发布了另外两个有问题的行,这些行在getter中。第一个是
return self.scale;
在- (CGFloat)scale
内。与之前类似,此点符号并不意味着您可能认为它意味着什么。事实上,这意味着
return [self scale];
和以前一样,这会导致无限递归。第二个是
if (!self.scale) {
出于同样的原因,这是一个问题:表达式self.scale
,当评估时是[自我尺度]。同样,这会导致无限递归。对这两个问题的解决方法是将self.scale
替换为_scale
,让您使用此getter:
- (CGFloat)scale
{
if (!_scale) {//Since CGFloat is not an object, this means <<if (_scale == 0) {>>
return DEFAULT_SCALE;
} else {
return _scale
}
}
你在这里做的工作比你真正应该做的要多得多。利用初始化程序会好得多:
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
{
self.scale = DEFAULT_SCALE;
}
}
这将保证如果未设置scale
,则会返回DEFAULT_SCALE
。这允许您完全消除吸气剂(因此,@synthesize
)。由于您在设置器中调用了-setNeedsDisplay
,因此您仍然需要它。
- (void)setScale:(CGFloat)scale
{
if (_scale != scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
答案 2 :(得分:1)
我可以想到有3种方法可以做到这一点,并且0知道。
@interface someClass
{
BOOL useCustomScale;
}
@property float scale;
@end
@implimentation someClass
-(float)scale
{
if(useCustomScale)
{return scale;}
return defaultScale;
}
-(void) setScale: (float)someScale
{
useCustomScale = YES;
scale = someScale
}
否则您可以使用NSNumber来支持比例值...
否则你可以将比例初始化为-1并将其设置为setter中的非法值
0通常是用于测试的非常糟糕的事情,因为您可能希望0成为有效值。