0

Let's start with this playground example

Example 1

import UIKit

internal final class TestClass1 {
    var testVar: Int = 1

    internal init() {
        print("TestClass1 init is called!")
    }

    deinit {
        print("TestClass1 deinit is called!")
    }

    internal func func1() {
        print("func1 is called!")
    }
}

internal final class TestClass2 {
    init() {
        let testClass1: TestClass1 = TestClass1()
        testClass1.testVar = 10
    }
}

var testClass2: TestClass2 = TestClass2()

Output

TestClass1 init is called!

TestClass1 deinit is called!

Example 2

import UIKit

internal final class TestClass1 {
    internal final var funcPointer: (() -> ())!

    internal init() {
        self.funcPointer = self.func1
        print("TestClass1 init is called!")
    }

    deinit {
        print("TestClass1 deinit is called!")
    }

    internal func func1() {
        print("func1 is called!")
    }
}

internal final class TestClass2 {
    init() {
        let testClass1: TestClass1 = TestClass1()
        testClass1.funcPointer()
    }
}

var testClass2: TestClass2 = TestClass2()

Output

TestClass1 init is called!

func1 is called!

My problem is, that the deinit() method is never called in example 2. I think there is a retain cycle but I don't know how to fix it.

I found this example and this SO post but I can't implement it in my example code.

PascalS
  • 975
  • 1
  • 16
  • 40
  • The question – as well as the previous one – is not particularly related to Swift 5 – vadian May 28 '19 at 18:46
  • I edited the title – PascalS May 28 '19 at 18:49
  • 1
    You already linked to https://stackoverflow.com/a/28138300/1187415, in your case that would be something like `self.funcPointer = { [unowned self] in self.func1() }` – Martin R May 28 '19 at 18:55
  • 2
    Btw, don't test this in a Playground: https://stackoverflow.com/questions/24363384/deinit-method-is-never-called-swift-playground – Martin R May 28 '19 at 18:56
  • 1
    This is a perfect example where the "closures are function pointers" notion (from your previous question) breaks down completely. In this context, a closure is a heap allocated (and ARCed) object that stores a strong reference to `self` (causing the strong retain cycle that's keeping `self` alive), in addition to the pointer to the function implementation. – Alexander May 28 '19 at 19:00

1 Answers1

4

To fix it, you have to call the func1 through weak self.

internal init() {
    self.funcPointer = { [weak self] in
        self?.func1()
    }
    print("TestClass1 init is called!")
}

This way you can prevent retain cycles.

What happens at the moment is that you are assigning an instance function to your instance property who now has a strong reference to your function.

Hope this helps.

Duy Tran
  • 101
  • 6