用于初始化弱属性的惯用法?

时间:2014-03-19 18:15:30

标签: ios objective-c

我有一个UIView子类,可以操作多个层。因为视图的图层sublayers强烈保留了图层,我的想法是让我自己对它们的引用很弱:

@interface AnchorCell : UICollectionReusableView
@property (weak, nonatomic) CAShapeLayer *link;
@property (weak, nonatomic) CATextLayer *offset;
@end

我可以在初始时进行一定数量的设置。但我最终编写了这样的代码:

- (void) initLink {
    CAShapeLayer *shape = _link = [CAShapeLayer layer]; // have to put it in local variable to make it last long enough to get to the sublayer
    _link.strokeColor = [[UIColor orangeColor] colorWithAlphaComponent: 1].CGColor;
    _link.fillColor = nil;
    _link.lineWidth = 3;
    _link.masksToBounds = NO;
....
    [self.layer addSublayer: _link];
}

我很好奇是否有更好的习惯方式来做到这一点。关于上述内容我喜欢的是,它尽可能地突出显示我设置了link变量,而不是一些本地shape变量,然后我在最后设置为link。我不喜欢的是你必须添加一个局部变量,因为Xcode没有明确的警告。

可以addSublayer:移到方法的顶部:

- (void) initLink {
    CAShapeLayer *shape = [CAShapeLayer layer];
    [self.layer addSublayer: shape];
    _link = shape;
    _link.strokeColor = [[UIColor orangeColor] colorWithAlphaComponent: 1].CGColor;
    _link.fillColor = nil;
    _link.lineWidth = 3;
    _link.masksToBounds = NO;
}

但这也隐藏了(对我来说)。它并没有明确表示已将link添加为子图层。此外,有时,在在其他地方注册之前,您必须对该对象进行一定程度的设置。

有更优雅的方式吗?或者至少有一种更为惯用的方式,考虑到ARC管理的ObjectiveC的限制?

3 个答案:

答案 0 :(得分:4)

我认为您不应该仅仅为了避免使用局部变量来创建属性strong(如果属性为weak,则需要局部变量)。

我认为内存语义(例如weak vs strong vs copy)应该反映功能对象所有权图,而不是为了避免使用局部变量。我会将该属性保留为weak,然后执行明显的操作:

CAShapeLayer *shape = [CAShapeLayer layer]; // have to put it in local variable to make it last long enough to get to the sublayer
shape.strokeColor = [[UIColor orangeColor] colorWithAlphaComponent: 1].CGColor;
shape.fillColor = nil;
shape.lineWidth = 3;
shape.masksToBounds = NO;
....
[self.layer addSublayer: shape];

self.link = shape;

就我个人而言,我不认为在一行代码中分配shape_link的行提高了它的可读性,所以我更喜欢将它们分开,但是做任何你想做的事情。

此外,我通常建议使用setter,因为我永远不知道我是否可能有一个自定义setter或在将来某个日期更改内存语义(这里的代码不应该关注它)。不止一次,我不得不重构直接使用ivar的代码,因为一些实现细节在以后发生了变化,但我还没有后悔使用访问器方法。

答案 1 :(得分:1)

您可能需要尝试代码块评估,如this blog post

中所述

像:

    _link = ({
        CAShapeLayer *shape = [CAShapeLayer layer];
        shape.strokeColor = [[UIColor orangeColor] colorWithAlphaComponent: 1].CGColor;
        shape.fillColor = nil;
        shape.lineWidth = 3;
        shape.masksToBounds = NO;
        [self.layer addSublayer: shape];
        shape;
    )};

答案 2 :(得分:0)

我认为你根本不需要临时变量形状 - 只需:

_link = [CAShapeLayer layer];

self.link = [CAShapeLayer layer];

请注意,如果你成为子图层后再也不需要_link那么你可以使用局部变量完成所有操作并跳过@property。

希望这有帮助。