考虑以下常见的简单类型擦除方案
protocol Foo {
associatedtype Bar
func bar() -> Bar
}
struct AnyFoo<Bar>: Foo {
private let _bar: () -> Bar
init<F: Foo>(_ foo: F) where F.Bar == Bar {
_bar = foo.bar
/* stores a reference to foo.bar,
so foo kept alive by ARC? */
}
func bar() -> Bar {
return _bar()
}
}
假设上面的初始化参数foo
是(意图是)&#34; large&#34;的临时实例。类型,我们从中只对切出Foo
蓝图的信息(即bar()
方法)感兴趣。
struct Huge { /* ... */ }
struct Foobar: Foo {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
func getAnyFooStr() -> AnyFoo<String> {
let foobar = Foobar()
return AnyFoo(foobar)
}
let anyStrFoo = getAnyFooStr()
/* we can now access anyStrFoo.bar() (-> "foo") from our
erased type, but do lotsOfData of the underlying seemingly
temporary Foobar() instance still "live", unreachable? */
foo
的剩余内容保留在内存中且无法访问?如果是这样,我认为我们永远无法回收这种丢失但活着的内容? (我尝试使用Foobar
作为课程进行上述操作,监控(缺少一个)deinit
电话,但是我在最后一个小时内对自己感到很困惑需要一些非自我验证,特别是对于Foobar
是值类型的情况)
Xcode 8.0 / Swift 3。
答案 0 :(得分:2)
是的,它与类型擦除无关:)
闭包Foobar().bar
保留它绑定的实例
(只要封闭处于活着状态),它的所有属性都会存活。
这是一个简化的例子:
class Huge {
deinit { print("deinit Huge") }
}
struct Foobar {
internal func bar() -> String {
return "foo"
}
let lotsOfData: Huge = Huge()
}
do {
let fb = Foobar().bar // the type of `fb` is `() -> String`
print("still alive ...")
}
print("... out of scope now")
输出:
still alive ... deinit Huge ... out of scope now