Skip to content

Instantly share code, notes, and snippets.

@dduan
Created July 28, 2020 03:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dduan/8e5fe939b53fc49177cc15cd36f591f5 to your computer and use it in GitHub Desktop.
Save dduan/8e5fe939b53fc49177cc15cd36f591f5 to your computer and use it in GitHub Desktop.
This property wrapper guarantees that a closure does nothing if its enclosing object is deinitialized.
@propertyWrapper
struct Escaping {
typealias Closure = () -> Void
var store: Closure
var wrappedValue: Closure {
get { self.store }
set { self.store = newValue }
}
init(wrappedValue: @escaping Closure) {
self.store = wrappedValue
}
static subscript<EnclosingSelf: AnyObject, FinalValue>(
_enclosingInstance observed: EnclosingSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, FinalValue>,
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Self>
) -> Closure
{
get {
{ [weak observed] in
guard let this = observed else {
return
}
this[keyPath: storageKeyPath].store()
}
}
set {
observed[keyPath: storageKeyPath].store = newValue
}
}
}
class Thing {
@Escaping
var method = {
print(42)
}
}
var f: () -> Void = {}
do {
let t = Thing()
f = t.method
f() // prints 42
}
f() // does not print 42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment