gpt4 book ai didi

objective-c - 何时重写 objective c getters

转载 作者:可可西里 更新时间:2023-11-01 06:18:19 25 4
gpt4 key购买 nike

在过去的一年中,我第一次与其他人一起参与了一些 Objective-C 项目。

偶尔(而且越来越多)我看到其他人覆盖 getter/accessor 方法,并在此方法中包含实现代码!对我来说,这是一个疯狂的小镇,因为这是拥有 setter 的全部意义……这也意味着在 setter 中设置的属性将在 getter 中被覆盖,因此毫无意义。

是这些人行为不端,还是我错过了什么?是否需要覆盖合成属性的 getter 方法?

例子:

@synthesize width;

- (CGFloat)width {
NSNumber *userWidth = [[NSUserDefaults standardUserDefaults] objectForKey:@"USER_WIDTH"];

if (userWidth != nil)
{
width = [NSNumber floatValue];
}

//Shouldn't the above lines be done in the SETTER? I have SET the property!
//Why would I ever need to write anything BUT the below line??
return width;
}

- (void)setWidth:(CGFloat)newWidth {
//THIS is where you do the the setting!
width = newWidth;
}

更新:

好的宽度是一个不好的例子。太多人陷入“变量是什么”和“不包括 get in objective-c 访问器”的语义。所以我更新了上面的示例以忽略不相关的语义,并专注于概念。这个概念是......当你想要覆盖 GETTER(不是 setter,只是 getter。我多次覆盖 setter,这个问题是关于 getter)时,是否有任何例子?

返回另一个属性,如图层(如下所述)是一个真实的例子。但更具体地说,是否需要在 GETTERSET 属性?这是我看到的一些奇怪现象,所以我更新了上面的 setter/getter 以从 NSUserDefaults 中提取一个值来帮助我的观点......

最佳答案

首先,Cocoa 命名约定会调用 getter -width,而不是 -getWidth。 “获取”用于填充传入的参数:

- (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 与我的访问器混合使用;)

关于objective-c - 何时重写 objective c getters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9797809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com