Управление памятью: сохранение цикла со слабой переменной, отсутствие сохранения цикла с неизвестным. Зачем? - PullRequest
0 голосов
/ 29 октября 2018

TL; DR * * 1001

У меня есть структура и класс. Структура имеет ссылку на экземпляр класса, а объект имеет замыкание, которое захватывает структуру. Если ссылка на объект неизвестна , кажется, что они оба деинициализированы. Если ссылка на объект слабая , они сохраняют друг друга. Почему?

У меня есть структура и класс, которые могут ссылаться друг на друга, и я пытался выяснить, как сохранить циклы и как их разорвать. Так что я немного поиграл с детской площадкой.

Учитывая этот код:

    struct A {
    unowned var b: B

    init(b: B) {
        self.b = b
    }

    func setup() {
        print("A setup")

        b.didSomethingClosure = {
            print("A: b did do something")
            self.printSomething()
        }
    }

    func printSomething() {
        print("A: A did do something")
    }
}

class B {

    var didSomethingClosure:(() -> Void)?

    func doSomething() {
        print("B: do something")
        didDoSomething()
    }

    func didDoSomething() {
        print("B: did something")
        if let closure = didSomethingClosure {
            closure()
        }
    }

    deinit {
        print("B: deinit")
    }
}


do {

    let b = B()
    let a = A(b: b)

    a.setup()
    b.doSomething()

    print("end do")
}

Если переменная b в структуре объявлена ​​как unowned var b: B, объект B освобождается. Если я изменю код на weak var b: B?, а затем b?.didSomethingClosure = ..., объект B будет сохранен. Почему?

1 Ответ

0 голосов
/ 29 октября 2018

Полагаю, проблема в том, что вы запускаете его в Playground. Попробуйте запустить его в реальном приложении, и вы увидите, что B освобожден

struct A {
    weak var b: B?

    init(b: B) {
        self.b = b
    }

    func setup() {
        print("A setup")

        b?.didSomethingClosure = {
            print("A: b did do something")
            self.printSomething()
        }
    }

    func printSomething() {
        print("A: A did do something")
    }
}

class B {

    var didSomethingClosure:(() -> Void)?

    func doSomething() {
        print("B: do something")
        didDoSomething()
    }

    func didDoSomething() {
        print("B: did something")
        if let closure = didSomethingClosure {
            closure()
        }
    }

    deinit {
        print("B: deinit")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let b = B()
        let a = A(b: b)

        a.setup()
        b.doSomething()

        print("end do") // B is deallocated here
    }
}
...