一次将多个引用类型值设置为nil

时间:2018-07-20 14:09:12

标签: swift null reference-type

假设我有一个UIView?数组,它们的默认值是:

var firstView: UIView? = UIView()
var secondView: UIView? = UIView()
let views = [firstView, secondView]

我想将数组中的每个值更改为nil。理想的解决方案是遍历数组的元素并将它们设置为nil。但是,这不起作用:

print(firstView) //Optional(<UIView: [address]; frame = (0 0; 0 0); layer = <CALayer: [address]>>)

for i in 0 ..< views.count {
    views[i] = nil
}

//firstView is still not nil
print(firstView) //Optional(<UIView: [address]; frame = (0 0; 0 0); layer = <CALayer: [address]>>)

对此有什么解决方案?

2 个答案:

答案 0 :(得分:1)

您可以使用KeyPath s:

class Foo {
    let views = [\Foo.view1, \Foo.view2]

    var view1: UIView? = UIView()
    var view2: UIView? = UIView()

    func freeAll() {
        print(view1 as Any, view2 as Any)

        for keyPath in views {
            self[keyPath: keyPath] = nil
        }

        print(view1 as Any, view2 as Any)
    }
}

let foo = Foo()
foo.freeAll()

输出:

Optional(<UIView: 0x7fc5c4107bb0; frame = (0 0; 0 0); layer = <CALayer: 0x60000213e760>>) Optional(<UIView: 0x7fc5c41057a0; frame = (0 0; 0 0); layer = <CALayer: 0x60000213d780>>)
nil nil

在这种情况下,views数组不包含对对象的引用,而是存储了KeyPath,您可以将它们视为如何找到它们的指导。这样一来,您就可以访问对象,并根据需要将它们设置为nil

答案 1 :(得分:0)

As MartinR said in this comment,无法直接修改实例变量的地址。此问题的一些可能的解决方案:

  • As MartinR points out,您只能将视图存储在该数组中,而不能存储在其他任何地方。这样,当您在数组nil中创建每个元素时,视图将没有任何引用。但是,这很容易产生太长或难以理解的代码。
  • 对于UIView来说,通常更好的解决方案是创建自定义视图,然后将所有要存储在其中的元素放入数组中。这样,您可以轻松地使一个视图nil和所有子视图成为nil(因为它们依赖于父视图)。