首先,Cocoa 命名约定将 getter 称为 -width,而不是 -getWidth。 “Get”用于填写传入的参数:
- (void) getWidth:(CGFloat *)outWidth
{
if (outWidth) *outWidth = _width;
}
也就是说,回到你原来的问题:
在过去,在 @property 和 @synthesize 之前,我们必须像上面那样手动编写访问器。
但是,在其他情况下,您可能希望手动编写访问器。
一个常见的方法是延迟初始化,直到需要一个值。例如,假设有一个图像需要一段时间才能生成。每次修改会改变图像的属性时,您都不想立即重绘图像。相反,您可以将抽签推迟到下一次有人询问时:
- (UIImage *) imageThatTakesAwhileToGenerate
{
if (!_imageThatTakesAwhileToGenerate) {
// set it here
}
return _imageThatTakesAwhileToGenerate;
}
- (void) setColorOfImage:(UIColor *)color
{
if (_color != color) {
[_color release];
_color = [color retain];
// Invalidate _imageThatTakesAwhileToGenerate, we will recreate it the next time that the accessor is called
[_imageThatTakesAwhileToGenerate release];
_imageThatTakesAwhileToGenerate = nil;
}
}
另一个用途是将访问器/修改器的实现转发到另一个类。例如,UIView 将其许多属性转发给支持CALayer:
// Not actual UIKit implementation, but similar:
- (CGRect) bounds { return [[self layer] bounds]; }
- (void) setBounds:(CGRect)bounds { [[self layer] setBounds:bounds]; }
- (void) setHidden:(BOOL)hidden { [[self layer] setHidden:hidden]; }
- (BOOL) isHidden { return [[self layer] isHidden]; }
- (void) setClipsToBounds:(BOOL)clipsToBounds { [[self layer] setMasksToBounds:clipsToBounds]; }
- (BOOL) clipsToBounds { return [[self layer] masksToBounds]; }
更新到提问者的更新:
在您的更新中,看起来有问题的代码要么尝试使用 NSUserDefaults 保留宽度值,要么尝试允许用户指定自定义值以覆盖所有返回的宽度。如果是后者,你的例子很好(尽管我会限制这种做法,因为它可能会给新手造成混淆)。
如果是前者,您希望从 NSUserDefaults 加载一次值,然后在 setter 中将新值保存回 NSUserDefaults。例如:
static NSString * const sUserWidthKey = @"USER_WIDTH";
@implementation Foo {
CGFloat _width;
BOOL _isWidthIvarTheSameAsTruthValue;
}
@synthesize width = _width;
- (CGFloat) width
{
if (!_isWidthIvarTheSameAsTruthValue) {
NSNumber *userWidth = [[NSUserDefaults standardUserDefaults] objectForKey:sUserWidthKey];
if (userWidth != nil) _width = [NSNumber doubleValue];
_isWidthIvarTheSameAsTruthValue = YES;
}
return _width;
}
- (void) setWidth:(CGFloat)newWidth
{
if (_width != newWidth) {
_width = newWidth;
NSNumber *userWidthNumber = [NSNumber numberWithDouble:_width];
[[NSUserDefaults standardUserDefaults] setObject:userWidthNumber forKey:sUserWidthKey];
_isWidthIvarTheSameAsTruthValue = YES;
}
}
@end
_width ivar 被用作缓存。真相存储在 NSUserDefaults 中。
注意:我在这个例子中使用了 NSUserDefaults,因为你在你的例子中使用了它。在实践中,我更喜欢不将 NSUserDefault 与我的访问器混合使用 ;)