4

这是我经常遇到的一种情况,足以使样板代码浪费,而且我确信我不能是唯一的。这是单调的,有没有更好的方法,还是我每次都必须这样做?

@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

现在这引发了一个编译警告,我没有吸气剂,我可以添加

- (CGFloat)insetMargin {
    return _insetMargin;
}

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

@interface SomeUIElement () {
    CGFloat _insetMargin;
}

这意味着我们只是想在属性更改时强制显示更新,因此开销很大。

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

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

4

1 回答 1

5

如果属性被声明为非原子的,您可以获得“部分综合”:

@property (nonatomic) CGFloat insetMargin;

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

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

于 2013-08-03T01:05:06.813 回答