objective-c - 何时重写 objective c getters

标签 objective-c ios xcode properties getter-setter

在过去的一年中,我第一次与其他人一起参与了一些 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/

相关文章:

ios - 从任意位置播放声音

iphone - 对数组中的日期进行排序

ios - 何时使用 show Segues 何时使用 Show detail Segues

iphone - 在一个 View Controller 中强制肖像使其他 View Controller 最初处于肖像

ios - Xcode:如何使用多个 "Display Name"值,每个配置都不同?

objective-c - 检查 mapView 是否已经包含注释

iphone - 如何在同一标签上使用不同颜色

objective-c - 对于 xCode 中的 XMLparser,我要测试什么字符串名称?

ios - 如何与 iOS 共享文件?

objective-c - Objective C : Version of JSON library I'm compiling in present in another library I'm linking in via . a,如何解决冲突?