(这个问题可能需要一个更具描述性的标题,请随时改进)
我有一个带有属性的 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 之前执行强保留。
我用 subviews
和 recognizers
来解决这个问题,所以我想我会很聪明,写一个 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
属性是 weak
。
你说得对,因为标签是通过调用 addSubview:
保留的。
但如果标签从其父 View 中删除,label
属性将变为 nil
,标签将丢失。因此,如果标签有可能被删除,但您想保留对标签的引用(可能稍后再添加),则将您的属性更改为 strong
。
self.label =
实际上只是 [self setLabel:]
,这也是正确的。之所以可以将 this 传递给 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/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |