从闭包的实例属性访问self

时间:2014-06-19 11:09:37

标签: swift

我使用的是Xcode6-beta2,但自从第一个公开测试版以来,我遇到了同样的问题。 Obj-C UIViewController的My Swift子类如下所示:

class SomeVC: UIViewController {
    var c1: () -> () = {
        println(self)
    }

    var c2: () -> () {
        get {
            return { println(self) }
        }
    }

    var c3: () -> () {
        return { println(self) }
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        c1()
        c2()
        c3()
    }
}

当显示VC时,我看到打印出以下行:

(Function)
<_TtC12SwiftiOSTest6SomeVC: 0x10bf1ed10>
<_TtC12SwiftiOSTest6SomeVC: 0x10bf1ed10>

(c2和c3的不同之处仅在于,如果计算属性只能获取,则不必包含get {...}。)

所以,第一个闭包的 self 似乎是指函数/闭包类型本身,而其他的那些&#39; self 指的是视图控制器(正如我所料)。 c1和c2 / c3之间的唯一区别是前者是存储属性,后者是计算属性,但我仍然希望闭包及其捕获值相同,即 self 总是请参阅附上的课程。现在的方式,似乎没有明显的方法让 c1 闭包来访问封闭类的方法/属性。

这是在某处记录的(我阅读了Swift书并没有找到任何东西),或者它只是某种类型的beta编译器错误,应该在某处提交?

1 个答案:

答案 0 :(得分:58)

这看起来很有趣。所以我做了调查。您可以在闭包内访问类实例变量,如self.instanceVariable。那时关闭将 捕获 其中的self。所以现在self引用了类实例本身。你的闭包应该是 lazy 属性。

  

惰性属性意味着你可以在默认闭包中引用self,因为在初始化完成并且已知self存在之后才会访问lazy属性。

您缺少 @lazy ,因此关闭时未知self这就是为什么它打印为(Function)我的猜测。< / p>

class TableViewController: UIViewController {
var name = "anil"
// Since swift 2.0 came out @lazy is replaced by lazy
lazy  var c1: () -> () = {
    println(self)
    println(self.name)

}

var c2: () -> () {
get {
    return { println(self) }
}
}

var c3: () -> () {
return { println(self) }
}


  override func viewDidLoad() {
        super.viewDidLoad()
        c1()
        c2()
        c3()
        }
}

输出

  

&lt; _TtC12TableViewApp19TableViewController:0x10d54e000&gt;

  阿尼尔
  &lt; _TtC12TableViewApp19TableViewController:0x10d54e000&gt;   &lt; _TtC12TableViewApp19TableViewController:0x10d54e000&gt;


更新

为类实例变量分配闭包会产生强引用周期。你应该避免这种情况。 Swift使用捕获列表来实现

  

如果为类实例的属性分配闭包,并且闭包通过引用实例或其成员来捕获该实例,则将在闭包和实例之间创建一个强引用循环。 Swift使用捕获列表来打破这些强大的参考周期。有关详细信息,请参阅Strong Reference Cycles for Closures

所以关闭的正确用法可能是

@lazy  var c1: () -> () = {
    [unowned self] in
    println(self)
    println(self.name)

}

参考:Swift programming guide

修改
@lazy 已更改为懒惰