objective-c属性-getter和setter
在UIView子类中,我具有以下属性:objective-c属性-getter和setter,objective-c,ios,uiview,getter-setter,Objective C,Ios,Uiview,Getter Setter,在UIView子类中,我具有以下属性: @property (nonatomic) CGFloat scale; #define DEFAULT_SCALE 0.90 还有这个能手和能手: -(CGFloat)scale { if (!self.scale) { return DEFAULT_SCALE; }else{ return self.scale; } } -(void)setScale:(CGFloat)scale {
@property (nonatomic) CGFloat scale;
#define DEFAULT_SCALE 0.90
还有这个能手和能手:
-(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的正确方法是什么,这样我就不会得到无限循环?您应该能够通过
\u scale
直接访问ivar。然后,您的getter/setter将如下所示:
更新:正如@Wattson 12在下面的评论中指出的,您需要在实现中添加一个@synthesis
@synthesize scale = _scale;
-(CGFloat)scale
{
if (!_scale) {
return DEFAULT_SCALE;
}else{
return _scale;
}
}
-(void)setScale:(CGFloat)scale
{
if (scale != _scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
二传手
在你贴在这里的那条线上
self.scale = scale;
您没有分配给局部变量。实际上,您正在将消息-setScale:
发送到self
。这条线相当于
[self setScale:scale];
由于您正在从-setScale:
内部调用-setScale:
,因此得到了这个无限递归
您需要做的是在setter中设置一个实例变量(而不是从setter内部调用它)。通常,只是通过写作
@property (nonatomic) CGFloat scale;
您已经创建了一个实例变量\u scale
但是,因为您同时覆盖了-scale
和-setScale:
,所以不会创建此实例变量。因此,您需要自己添加实例变量。在类的声明@接口中
(或者,在@接口中
)
完成此操作后,将行更改为
_scale = scale;
吸气剂
您还发布了另外两个有问题的行,它们位于getter中。首先是
return self.scale;
内部-(CGFloat)刻度
。与之前类似,此点符号的含义与您可能认为的不同。事实上,这意味着
return [self scale];
和以前一样,这会导致无限递归。二是
if (!self.scale) {
这是一个问题,原因相同:表达式self.scale
,在计算时为[self scale]。同样,这会导致无限递归。解决这两个问题的方法是用\u scale
替换self.scale
,这样您就有了这个getter:
- (CGFloat)scale
{
if (!_scale) {//Since CGFloat is not an object, this means <<if (_scale == 0) {>>
return DEFAULT_SCALE;
} else {
return _scale
}
}
这将保证如果未设置scale
,它将返回默认值\u scale
。这允许您完全消除getter(因此,@synthesis
)。由于您正在setter中调用-setNeedsDisplay
,因此仍然需要它
- (void)setScale:(CGFloat)scale
{
if (_scale != scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
嗯,我可以想出三种方法来做到这一点,并且要注意
@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是有效值。我得到了“使用未声明的标识符'\u scale'”。您是否在属性中使用了
@synthesis
?您是否在界面中创建了scale
变量?如果您同时覆盖setter和getter,则无法获得自动合成功能,您将需要添加@synthesis scale=\u scale;是的,这就是问题所在。我通常不需要合成,因为Xcode会自动合成。如果覆盖getter和setter,就不需要@synthesis。只需添加您自己的ivar,并让方法使用ivar.+1进行解释。这就是我的想法,但我不知道编写自己的getter/setter意味着必须合成属性。@soleil我强烈建议您尝试一下我在标题“更好的方法”下所写的内容。您所做的工作比实际需要的要多得多。为什么只删除getter会消除@synthetic?@soleil您只需要@synthetic
,因为您同时覆盖了setter和getter。消除其中一个覆盖后,将自动为您创建\u scale
实例变量。
- (void)setScale:(CGFloat)scale
{
if (_scale != scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
@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
}