Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Shows how Swift's instance methods actually all capture self, due to the underlying implementation. Read the whole explanation: http://rosslebeau.com/2016/sneaky-reference-cycles-swift-instance-methods
func weakify<A: AnyObject, B>(obj: A, target: ((A) -> (B) -> Void)?) -> ((B) -> Void) {
return { [weak obj] value in
guard let obj = obj else { return }
target?(obj)(value)
}
}
class Actor {
var action: () -> Void
init() {
action = {}
}
}
class NormalActor: Actor {
deinit {
print("Normal deiniting")
}
func setDefaultAction() -> Void {
action = {
print("Normal action")
}
}
}
class UnsafeActor: Actor {
deinit {
print("UnsafeActor deiniting")
}
func setDefaultAction() -> Void {
action = printThings
}
func printThings() -> Void {
print("Unsafe action")
}
}
class SafeActor: Actor {
deinit {
print("SafeActor deiniting")
}
func setDefaultAction() -> Void {
action = weakify(obj: self, target: SafeActor.printThings)
}
func printThings() -> Void {
print("Safe action")
}
}
// Use this function to create a scope
// All objects created inside should be deallocated at the end of the function
// You will see that UnsafeActor's deinit is never called
func strongReferenceCycleTest() {
let normalActor = NormalActor()
normalActor.setDefaultAction()
normalActor.action()
let unsafeActor = UnsafeActor()
unsafeActor.setDefaultAction()
unsafeActor.action()
let safeActor = SafeActor()
safeActor.setDefaultAction()
safeActor.action()
}
strongReferenceCycleTest()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment