IBOutlet 的只读属性是否有效?它是否更好?

发布于 2024-12-13 05:18:03 字数 640 浏览 0 评论 0原文

在我继承的代码中,我看到了以下内容:

@property (readonly) IBOutlet UIImageView * bgImage;

当我期望像这样的保留内存模型时:

@property (readonly, retain) IBOutlet UIImageView * bgImage;

我很困惑为什么第一个属性定义可以工作而不会引起问题。

另外,dealloc 中有一个 release 正如您所期望的那样:

-(void)dealloc
{
   [_bgImage release];
   [super dealloc];
}

如果有人能对此做出解释,我将不胜感激。我已经与原始开发人员交谈过,他试图编写更简洁的代码,这就是为什么他在内存模型中省略了 retain (似乎没有必要)。

我想知道 IBOutlet 是否基本上被视为 ivar IBOutlet 语句,因为它是只读的(没有可使用的 setter,因此默认分配内存模型没有区别)。

如果 IBOutlet 永远不会改变,那么使用没有内存模型的只读属性实际上是定义属性的更好方法吗?

In code that I'm inheriting, I've seen the following:

@property (readonly) IBOutlet UIImageView * bgImage;

When I would expect a retain memory model like:

@property (readonly, retain) IBOutlet UIImageView * bgImage;

I'm confused why the first property definition works without causing problems.

Also, there is a release in dealloc as you might expect like:

-(void)dealloc
{
   [_bgImage release];
   [super dealloc];
}

I'd appreciate if anyone can come up with an explanation for this. I've spoken with the original developer and he was trying to write more concise code which is why he left out the retain in the memory model (seemed unnecessary).

I wonder if the IBOutlet is basically treated like an ivar IBOutlet statement because it is readonly (no setter to use, thus the default assign memory model makes no difference).

If the IBOutlet is never expected to change, would using a readonly property with no memory model actually be a preferable way to define properties?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜还是长夜 2024-12-20 05:18:03

iOS 上的 nib 加载器在 nib 中创建对象,然后自动释放它们。当它与插座建立连接时,它使用 setValue:forKey:,它将调用该键的 setter 方法。如果没有定义 setter,例如当IBOutlet 是一个readonly 属性时,该对象在分配之前无论如何都会被保留。
(这是 资源编程指南中的管理 iOS 中的 Nib 对象。)

所以实际上,outlet 是否声明为retainassign,另一端的对象由具有插座的对象拥有。它要么由 setter 方法保留,要么在找不到 setter 时由 setValue:forKey: 保留。由于在第二种情况下没有其他可能的所有者,因此您可以将带有插座的对象视为所有者。因此nib中的对象应该在dealloc中释放。

我同意你的观点,应该通过更改属性属性以包含 retain 来明确此内存条件。* 无论它是否是 readonly 似乎都没有什么区别(但是,请参见下文)。从概念上讲,是的,该对象是只读的,因此是否将其显式标记为只读取决于您是否认为它是一个 IBOutlet 这一事实已得到适当记录。

更新:
Paul.s 下面的评论促使我做了一个快速测试。我创建了一个 UIView 子类,用于记录其 allocretainreleaseautorelease > 调用,将其实例插入笔尖,并通过属性为应用程序委托提供一个 IBOutlet

手动统计引用计数活动,当属性为 (readwrite, allocate) 时,实例的净计数为 0。当属性以推荐方式(readwrite,retain)声明时,它是net +1;当它是(readonly,assign)时,也是 >。所有这一切都与预期的一样——当它是(readwrite, allocate)时,分配setter用于建立连接,并且不进行保留。当它是只读时,连接机制会依靠执行自己的保留。

最有趣的是,当我尝试通过声明 (readwrite, allocate) 的属性更改此视图的背景颜色(即,当它可能已被释放时)来崩溃应用程序时,我看到了最后一个调用弹出retain

我认为归根结底是:遵循苹果的建议——他们知道幕后发生了什么,并且(除了错误)不会引导你走错路。

(另一件需要注意的事情是,一如既往,担心绝对引用计数不会很有用——在两次调用 的过程中,计数一度一路上升到 6 keeprelease ——您只需要担心直接引起的保留和释放。)


*当然,这在 ARC 下会发生变化。我解释的信息位于该章的“遗留模式”部分。在 ARC 下,建议将 IBOutlets 设置为 weak,除非它们是顶级的,在这种情况下,它们应该strong。这样做意味着您依赖视图层次结构(保留其子视图的视图)来维护自身。

The nib loader on iOS creates the objects in the nib and then autoreleases them. When it establishes connections to outlets, it uses setValue:forKey:, which will call the setter method for that key. If no setter is defined, such as when the IBOutlet is a readonly property, the object is retained anyways before being assigned.
(This is a paraphrase of Managing Nib Objects in iOS in the Resource Programming Guide.)

So in actual fact, whether the outlet is declared as retain or assign, the object at the other end is owned by the object with the outlet. Either it is retained by the setter method, or it is retained by setValue:forKey: when a setter is not found. Since there is no other possible owner in the second case, you may consider the object with the outlet to be the owner. Therefore the object in the nib should be released in dealloc.

I agree with you that this memory condition should be made explicit by changing the property attributes to include retain.* Whether or not it's readonly doesn't seem to make a difference (however, see below). Conceptually, yes, the object is read-only, so whether to mark it explicitly as such depends on whether you consider that suitably documented by the fact that it's an IBOutlet.

UPDATE:
Paul.s's comment below prompted me to do a quick test. I created a UIView subclass that logs its alloc, retain, release, and autorelease calls, stuck an instance of it into a nib, and gave the app delegate a IBOutlet via a property.

Tallying up the reference counting activity by hand, the instance came out with a net 0 count when the property was (readwrite, assign). It was net +1 when the property was declared the recommended way, (readwrite, retain), and also when it was (readonly, assign). All of this is pretty much as expected -- when it is (readwrite, assign), the assigning setter is used to make the connection, and no retain is made. When it is readonly, the connection mechanism falls back on doing its own retain.

Most interestingly, when I tried to crash the app by changing the background color of this view with the property declared (readwrite, assign) (i.e., when it had presumably been deallocated), I saw one last call to retain pop up.

I think what this comes down to is: follow Apple's recommendation -- they know what's going on behind the scenes, and (barring bugs) aren't going to steer you wrong.

(Another thing to take away is that, as always, worrying about absolute reference counts is not going to be terribly useful -- the count went all the way up to 6 at one point, over the course of two dozen calls to retain and release -- you just need to worry about retains and releases that you cause directly.)


*Of course, this changes under ARC. The info I paraphrased is in the "Legacy Patterns" section of its chapter. Under ARC, the recommendation is for IBOutlets to be weak unless they are top-level, in which case they should be strong. Doing it that way means you are relying on the view hierarchy (views retaining their subviews) to maintain itself.

锦上情书 2024-12-20 05:18:03

我向 Apple 报告了一个错误,如果您创建 IBOutlet 实例变量而不是属性,Xcode 仍会在 dealloc 等中自动创建版本。iOS 应用程序的 Xcode 似乎总是为 IBOutlet 创建版本,无论其正确与否。

我不喜欢属性 IBOutlet,因为这意味着您将它们声明为可读写,这意味着它们被记录为可读写,但大多数时候(几乎总是),IBOutlet 在概念上应该是只读的。显然它们必须是可读写的才能初始设置。

I have reported a bug with Apple that if you create IBOutlet instance variables instead of properties, that Xcode will still automatically create release's in dealloc etc. Xcode for iOS apps seems to always create releases for IBOutlet whether its correct or not.

Personnel I don't like property IBOutlet as it means you declare them as readwrite, which means they are documented as readwrite, but most of the time, (nearly always), IBOutlet should conceptually be readonly. Obviously they have to be readwrite to set initially.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文