gpt4 book ai didi

ios - 对属性 setter 的行为感到困惑

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:53 25 4
gpt4 key购买 nike

(这个问题可能需要一个更具描述性的标题,请随意改进)

我有一个带有属性的 UIView 子类:

@property (weak, nonatomic) UILabel *label;

initialize 方法中我有:

[self addSubview: (self.label = [UILabel new])];

我喜欢它的简洁,但我对它的工作原理有疑问。

首先,我收到警告:

Assigning retained object to weak property; object will be released after assignment

撇开警告不谈,它似乎确实有效。那是因为在发布机制可以运行之前,addSubview: 重新保留了它吗?

如果我理解正确,self.label = ... 代码只是 [self setLabel: ...] 的糖分。但是如果我用我自己的 setLabel: 实现覆盖属性访问,它的签名将是

- (void) setLabel: (UILabel*) label;

因此返回值为void。但它被送入 addSubview: 发送和工作?那么它是如何工作的呢?

更新

在这里做单行代码的事情之一是 Objective-C 倾向于避免从像 addSubview: 这样的方法返回有用的信息,这与Smalltalk 的影响首先产生了 Objective-C。在 Smalltalk 中,addSubview: 方法返回添加的对象是预期的/常见的。如果是这种情况,可以将这些表达式写成:

self.label = [self addSubview: [UILabel new]];

这将使强/弱语义变得快乐。 addSubview: 会在到达弱 label setter 之前执行强保留。

我用 subviewsrecognizers 来解决这个问题,所以我想我会聪明一点,写一个 category 来做一些事情像这样(我反转了接收者/参数,所以它很容易与备用 addSubview: 签名区分开来)。

@interface UIView (UIView_Adding)
- (UIView*) addedToView: (UIView*) superview;
@end

@interface UIGestureRecognizer (UIView_Adding)
- (UIGestureRecognizer*) addedToView: (UIView*) view;
@end

@implementation UIView (UIView_Adding)
- (UIView*) addedToView: (UIView*) superview {
[superview addSubview: self];
return self;
}
@end

@implementation UIGestureRecognizer (UIView_Adding)
- (UIGestureRecognizer*) addedToView: (UIView*) view {
[view addGestureRecognizer: self];
return self;
}
@end

不幸的是,这只是调用了丑陋守恒定律。我摆脱了一种警告,得到了另一种。包含该类别后,我现在可以写:

self.label = [[UILabel new] addedToView: self];

但这会生成一个警告,指出 self.label 是用来保存 UIView 的特定子类,即 UILabel 和返回类型addedToView: 的是 `UIView'。我不知道 Objective-C 伪类型,这意味着成为这个已知父类(super class)型的正确子类型以使属性类型快乐。 :(

最终更新

我发现了 instancetype 类型。通过更改我的类别方法签名以返回这些类型,一切正常。我是 instancetype 的新手,不知道我是否在这里滥用了某些东西,但我很高兴它起作用了。

最佳答案

警告来自:

self.label = [UILabel new]

因为您的 label 属性

你是正确的,它最终会起作用,因为调用 addSubview: 会保留标签。

但是如果标签从其父 View 中删除,label 属性将变为nil,并且标签将丢失。因此,如果标签有可能被删除,但您希望保留对该标签的引用(可能稍后将其添加回来),请将您的属性更改为 strong

您也说对了,self.label = 实际上只是 [self setLabel:]。之所以可以将其传递给 addSubview:,是因为 x = y 等表达式的值等于赋值。

所以:

[self addSubview: (self.label = [UILabel new])];

如果等同于:

UIView *view = (self.label = [UILabel new]);
[self addSubview:view];

关于ios - 对属性 setter 的行为感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26871193/

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