Created
July 14, 2020 04:59
-
-
Save samsonjs/c398f903b0d5fa66b15ce3ba323f0f83 to your computer and use it in GitHub Desktop.
Capture weak references but only call the closure when it hasn't been deallocated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
func weakOrBust<A: AnyObject>(_ a: A, _ f: @escaping (A) -> Void) -> () -> Void { | |
{ [weak a] in | |
guard let a = a else { | |
print("object disappeared") | |
return | |
} | |
f(a) | |
} | |
} | |
func weakOrBust<A: AnyObject, B: AnyObject>(_ a: A, _ b: B, _ f: @escaping (A, B) -> Void) -> () -> Void { | |
{ [weak a, weak b] in | |
guard let a = a, let b = b else { | |
print("at least 1 object disappeared") | |
return | |
} | |
f(a ,b) | |
} | |
} | |
func later(f: @escaping () -> Void) { | |
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: f) | |
} | |
class Monkey {} | |
var a = Monkey() | |
later(f: weakOrBust(a) { a in | |
print("first closure called?! a=\(a)") | |
}) | |
// Overwrite the first monkey right away causing it to disappear, and the first closure to be skipped. | |
a = Monkey() | |
later(f: weakOrBust(a) { a in | |
print("second closure called a=\(a)") | |
}) | |
// Everybody wants more monkeys. It's easy to make this work up to a reasonable | |
// number of arguments, say 3-5. It can go up to 11 if you want but please don't | |
// want that. | |
let b = Monkey() | |
later(f: weakOrBust(a, b) { a, b in | |
print("third closure called a=\(a) b=\(b)") | |
}) | |
// vs. the alternative | |
later(f: { [weak a, weak b] in | |
guard let a = a, let b = b else { return } | |
print("fourth closure called a=\(a) b=\(b)") | |
}) | |
// but on the other hand, you lose trailing closure syntax | |
later { [weak a, weak b] in | |
guard let a = a, let b = b else { return } | |
print("fifth closure called a=\(a) b=\(b)") | |
} | |
// sad trombone, this isn't valid syntax | |
// later weakOrBust(a) { a in | |
// print("a=\(a)") | |
// } | |
// it would be cool to write something like this and have it used as a literal closure, | |
// including trailing closure syntax | |
// @weakOrBust { a, b in /* a and b are strong references */ } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment