1

An application that I am working on, that uses ARC and needs to support iOS 4.3 and iOS 5, declares every outlet as @property (strong, nonatomic) IBOutlet in the .h file.

e.g.

// myClass.h
@property (strong, nonatomic) IBOutlet UITextView *myTextview;

I know that with ARC only properties which do not hold a strong reference to an object are released. As a result, the App relies on - (void)viewDidUnload to set the property myTextview to nil.

i.e.

// myClass.m

- (void)viewDidUnload
{ 
[super viewDidUnload];
self.myTextview = nil;  
}

I know, from Apple's Documentation, that Outlets should generally be weak except those from File's Owner ( i.e. A Runtime Object that owns the contents of the iOS Storyboard scene) to Top-Level Objects (my rule of thumb is to use anything that appears in the window with File's Owner, First Responder and View).

Anything I add to the view will be a subview and thus is retained by it's direct superview, meaning a weak reference should be used.

I am also aware that - (void)viewDidUnload is deprecated in iOS 6 and is not called.

1st Question : What are the issues with taking the approach of declaring every outlet as a strong property and setting it to nil in viewDidUnload, apart from the fact that viewDidUnload is deprecated in iOS 6?

My intuition tells me that it is because situations arise where you can set a pointer to nil, before viewDidUnload is called. So you should, to free up memory on the heap. Is there a noticable performance change if this is the case?

2nd Question : Should I go back throughout the project and change strong to weak? Why? Is it worth the time?

3rd Question : If I was to declare the property in a class extension, to 'hide' it, how does this affect my rule of thumb for deciding on when to use strong or weak.

I know there are many threads here that discuss this issue. But many I've found are out of date, and do not address this issue directly. Thanks.

4

2 回答 2

4

首先,您的一些假设需要解决:

我知道 ARC 只发布不持有对对象的强引用的属性。因此,App 依赖 - (void)viewDidUnload 将属性 myTextview 设置为 nil。

不完全的。ARC 从weak一开始就没有保留属性。至于strong属性,ARC 仍然会释放它们,但直到调用 dealloc 时才会释放它们。

viewDidUnload从未用于防止泄漏。这本质上是一种优化,Apple 认为不再值得麻烦。要理解,请考虑 iOS6 之前的视图控制器的标准生命周期:

1.分配
2a。查看已加载
2b。查看 Unloaded
3. Deallocated

其中2a2b可以重复任意次数。例如,导航堆栈底部的视图控制器(其视图被隐藏)可以在内存不足的情况下卸载其视图。然后它会在下一次它的视图变得可见时重新加载。

该方法本质上是在说“嘿,视图控制器程序员,我们的内存不足,无论如何没人能看到我,所以我要发布我的视图。如果你可以为你的强大属性做同样的事情,那就太好了。 "

这个过程很微妙,而且通常令人困惑。由于单调乏味,Apple 弃用了它。视图不再被卸载,因此没有必要实现它。关键是你所有的强属性仍然会在 ARC 的 dealloc 方法中释放。

我知道奥特莱斯通常应该很弱......

你为什么知道?奥特莱斯没有什么特别之处。'IBOutlet' 关键字实际上只是为了 Xcode 在使用其可视化工具设计事物时的好处。它对编译后的代码没有影响。因此,在考虑strongvs weakoutlets 时,请使用与任何其他属性相同的考虑因素,即“我需要它存在,还是我可以接受它消失在我身上?”。

除了 viewDidUnload 在 iOS 6 中被弃用之外,将每个 outlet 声明为强属性并在 viewDidUnload 中将其设置为 nil 的方法有什么问题?

没有问题。如果您希望您的属性与您的控制器一样存在,请使用strong. viewDidUnload与此无关。在较旧的 iOS 版本上,您可以viewDidUnload根据需要发布强大的插座。

我应该回到整个项目并从强变弱吗?为什么?值得花时间吗?

同样,只需使用对您的用例有意义的任何限定符。您使用strong网点几乎总是安全的。

如果我要在类扩展中声明该属性,以“隐藏”它,这将如何影响我决定何时使用强或弱的经验法则。

没有区别。

于 2013-05-02T17:03:45.127 回答
0

第一个问题:插座是主视图的子视图,是视图控制器的属性。如果您将它们声明为weak,则它们的保留计数为 1,因为它们是子视图。如果视图被释放,它们也被释放。如果将它们声明为strong,它们的保留计数为 2,因为它们是子视图,并且是视图控制器的强属性。所以它们只有在视图控制器被释放时才会被释放(它也释放它的视图和它的子视图)。据我了解,不同之处在于,当视图控制器的视图被释放时,例如当它没有呈现并且内存不足时,出口仍然在它们被声明为时分配内存strong
第二个问题:我相信在大多数情况下这并不重要。
第三个问题:我相信如果您在类扩展中声明属性,那么它们只是属于该类,因此与“真实”类属性相比,处理它们没有区别。
我的方法是确保不要声明属性,因为strong这可能会导致保留周期,会发生什么,即,如果您将委托声明为strong.

于 2013-05-02T16:14:09.020 回答