菜鸟教程小白 发表于 2022-12-12 12:41:06

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


                                            <p><p><em>(这个问题可能需要一个更具描述性的标题,请随时改进)</em></p>

<p>我有一个带有属性的 <code>UIView</code> 子类:</p>

<pre><code>@property (weak, nonatomic) UILabel *label;
</code></pre>

<p>在 <code>initialize</code> 方法中我有:</p>

<pre><code>)];
</code></pre>

<p>我喜欢它的简洁性,但我对它的工作原理有疑问。</p>

<p>首先,我收到一条警告:</p>

<pre><code>Assigning retained object to weak property; object will be released after assignment
</code></pre>

<p>除了警告之外,它实际上似乎有效。是不是因为在发布机制可以运行之前,<code>addSubview:</code> 重新保留它?</p>

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

<pre><code>- (void) setLabel: (UILabel*) label;
</code></pre>

<p>所以返回值是<strong>void</strong>。但它被送入 <code>addSubview:</code> 发送和工作?那么它是如何工作的呢?</p>

<h1>更新</h1>

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

<pre><code>self.label = ];
</code></pre>

<p>这将使强/弱语义感到高兴。 <code>addSubview:</code> 会在到达弱 <code>label</code>setter 之前执行强保留。</p>

<p>我用 <code>subviews</code> 和 <code>recognizers</code> 来解决这个问题,所以我想我会很聪明,写一个 <code>category</code> 来做点什么像那样(我颠倒了接收者/参数,因此很容易将其与备用 addSubview: 签名区分开来)。</p>

<pre><code>@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 {
    ;
    return self;
}
@end

@implementation UIGestureRecognizer (UIView_Adding)
- (UIGestureRecognizer*) addedToView: (UIView*) view {
    ;
    return self;
}
@end
</code></pre>

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

<pre><code>self.label = [ addedToView: self];
</code></pre>

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

<h1>最终更新</h1>

<p>我发现了 <code>instancetype</code> 类型。通过更改我的类别方法签名以返回这些类型,一切正常。我对 <code>instancetype</code> 还很陌生,不知道我是否在这里滥用了某些东西,但我很高兴它能奏效。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>警告来自:</p>

<pre><code>self.label =
</code></pre>

<p>因为您的 <code>label</code> 属性是 <code>weak</code>。</p>

<p>你说得对,因为标签是通过调用 <code>addSubview:</code> 保留的。</p>

<p>但如果标签从其父 View 中删除,<code>label</code> 属性将变为 <code>nil</code>,标签将丢失。因此,如果标签有可能被删除,但您想保留对标签的引用(可能稍后再添加),则将您的属性更改为 <code>strong</code>。</p>

<p><code>self.label =</code> 实际上只是 <code></code>,这也是正确的。之所以可以将 this 传递给 <code>addSubview:</code> 是因为像 <code>x = y</code> 这样的表达式的值等于赋值。</p>

<p>所以:</p>

<pre><code>)];
</code></pre>

<p>如果相当于:</p>

<pre><code>UIView *view = (self.label = );
;
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 对属性 setter 的行为感到困惑,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/26871193/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/26871193/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 对属性 setter 的行为感到困惑