在swift中,是否有必要在使用后将强变量设置为nil?

时间:2017-02-21 12:02:25

标签: ios swift

我基本上使用outlet作为弱变量,比如

@IBOutlet weak var testButton: UIButton!

但如果我使用强而不是弱,会发生什么,比如

@IBOutlet var testButton: UIButton!

使用后我是否必须将其设置为零?

2 个答案:

答案 0 :(得分:5)

你得到了一些不好的答案。

奥特莱斯通常是弱的,隐式解包的选项。这就是类型后的!表示的内容。

出口被声明为弱,以避免在不再需要后将视图层次结构保留在内存中。 (通常情况下,出口是由它的超级视图所拥有的,只需从它的超级视图中删除它就会导致它被取消分配。通常这是正确的行为。如果你想要一个出口继续它的后面和&# #39; s从它的超级视图中移除你可以创建另一个强大的引用或使出口强大,但在这种情况下,当你完成它时,它取决于你)

奥特莱斯应该被宣布为弱,只有极少数例外。是的,如果你声明它们很强大,那么当你完成它们时你应该把它们弄清楚。 (虽然如果你的视图控制器被取消分配,那么它并不重要,因为它的强引用会消失。)

答案 1 :(得分:4)

只要它们在屏幕上作为子视图,就会很好。实际上,它们将由superView的subviews数组保留。一旦它们从屏幕上移除(因此从subviews阵列中移除),retainCount将减少一个。如果出口的唯一强引用位于subviews数组(弱属性情况)中,则retainCount将为零,对象将被释放,并且您的testButton属性将变为零。在这种情况下,您永远无法重用testButton属性,因为它是强制解包的,任何访问都会导致崩溃。如果可以通过编程方式从屏幕中删除视图,那么将此属性设置为?可选是一个好主意。

如果您希望以编程方式从屏幕上删除此插座,并希望此属性获得对插座的强引用,并依次根据某些用户交互逻辑以编程方式将其添加为子视图。在这种情况下,具有强引用的removeFromSuperView方法将减少仍为1的保留计数,因为您的属性保留了对象。

如果您将强引用设置为nil,并且该对象不再是子视图,那么它将被取消分配,并且您将无法重用testButton属性。

如果您设置为nil强引用,但对象仍然是视图层次结构中的子视图,那么它将保留在那里直到其superview被销毁,但您将永远无法再次操作该对象,作为您的参考对象已经消失了。

一般情况下,如果在你的程序逻辑中,属性在其范围内可以变为nil,则将其声明为?可选而不是!强制解包可选是更安全的,因为展开的力将会如果在他们为零时访问则导致崩溃。

我希望自己足够清楚,并且回答了你的怀疑。

修改

以编程方式创建视图;首先,没有可供参考的出口是一个好主意。如果一个新的开发人员进入你的项目并看到一个出口,他希望在xib或故事板上找到相应的插座;他不希望通过代码看到这个插座。

无论如何,我们必须注意一些情况。但是所有这些都依赖于同样的规则:

  • 弱不会增加保留计数,强者确实。
  • 会立即取消分配保留count == 0的对象。
  • 指向已解除分配的实例的弱引用会立即更改为nil

要更好地理解:

weak var testButton: UIButton!

func createButton() {
    testButton = UIButton()
    //Here testButton is already nil, because testButton is weak and
    //the new UIButton is not retained.
    view.addSubiew(testButton) //crash, because you are accessing 
    //a nil force unwrapped property
}

将tesButton定义为强大,可以解决问题。

以下情况不同:

weak var testButton: UIButton!

func createButton() {
    let localTestButton = UIButton() //this is strong
    testButton = localTestButton //this is weak
    //here the new UIButton is retained by the localTestButton var
    //so its retainCount is 1, so testButton is not nil as its 
    //reference is not deallocated
    view.addSubview(testButton) //all good, this retains the UIButton
    //that now has a retain count of 2
    //At the end of the scope, all the local var are released, and
    //their pointed objects decreases the retainCount.
    //in this scope there is just the localTestButton that is released
    //so the pointed object's retain count decreases from 2 to 1.
    //if in another scope the subview is removed (testButton.removeFromSuperView())
    //then the UIButton retain count is 0 and it is deallocated.
    //testButton will immediately become nil and no longer usable.
}