Objective C Idioms - 属性,ivars和needsDisplay

时间:2013-08-03 00:59:32

标签: objective-c properties uikit ivar synthesize

这是我经常遇到的一种情况,足以使样板代码浪费而且我确信我不能成为唯一的代码。这是不同寻常的,是否有更好的方法,或者我每次都必须这样做?

@interface SomeUIElement : UIView
@property CGFloat insetMargin; // <-- just an example of a UI parameter
@end

@implementation SomeElement
- (void)setInsetMargin:(CGFloat)insetMargin {
    _insetMargin = insetMargin;
    [self setNeedsDisplay]; // <-- the only thing that stops it being synthesized
}
@end

现在这引发了一个编译警告,我没有一个getter,摆脱我可以添加

- (CGFloat)insetMargin {
    return _insetMargin;
}

但现在,它抱怨我没有ivar(因为定义的getter和setter意味着没有为我创建),所以我需要添加

@interface SomeUIElement () {
    CGFloat _insetMargin;
}

这意味着当属性发生变化时,我们只是想要强制显示更新。

是否有某种方式告诉ObjC我确实打算为我创建getter和ivar,所以我只需要编写setter,或者(b)更好的方式来请求显示更新视觉外观变化相关的属性?

Apple的SDK如何做到这一点(我假设我没有错过任何观看方式,比如UILabel来源)?

1 个答案:

答案 0 :(得分:5)

如果声明属性为非原子属性,则可以获得“部分合成”:

@property (nonatomic) CGFloat insetMargin;

默认(出于未知原因)是 atomic 。为了实现该原子性,两个访问器都必须使用相同的锁定机制。但是,当合成方法时,不会暴露该机制。因此,您必须实现两个访问器并创建自己的锁,或让编译器执行这两个操作并使用其锁定。

但是,如果属性不是原子属性,则可以显式实现三个元素的任意组合:ivar,setter或getter,编译器将负责其余部分。如果您想要从默认值更改ivar的名称(当前是带有前置下划线的属性名称),您还需要一个明确的@synthesize