Избегайте циклов сохранения для указателей функций в Swift

Начнем с примера с детской площадки.

Пример 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()

Выход

TestClass1 init is called!

TestClass1 deinit is called!

Пример 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()

Выход

TestClass1 init is called!

func1 is called!

Моя проблема в том, что метод deinit() никогда не вызывается в примере 2. Я думаю, что есть цикл сохранения, но я не знаю, как это исправить.

Я нашел этот пример и этот SO сообщение, но я не могу реализовать его в своем примере кода.

Вопрос — как и предыдущий — не особо связан со Swift 5

vadian 28.05.2019 20:46

я отредактировал заголовок

PascalS 28.05.2019 20:49

Вы уже связались с stackoverflow.com/a/28138300/1187415, в вашем случае это будет что-то вроде self.funcPointer = { [unowned self] in self.func1() }

Martin R 28.05.2019 20:55

Кстати, не проверяйте это на игровой площадке: stackoverflow.com/questions/24363384/…

Martin R 28.05.2019 20:56

Это прекрасный пример, когда понятие «закрытие является указателем на функцию» (из вашего предыдущего вопроса) полностью разрушается. В этом контексте замыкание — это выделенный в куче (и ARCed) объект, который хранит строгую ссылку на self (вызывая сильный цикл сохранения, поддерживающий self), в дополнение к указателю на реализацию функции.

Alexander 28.05.2019 21:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы исправить это, вы должны вызвать func1 через weak self.

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

Таким образом, вы можете предотвратить циклы сохранения.

Что происходит в данный момент, так это то, что вы назначаете функцию экземпляра своему свойству экземпляра, которое теперь имеет сильную ссылку на вашу функцию.

Надеюсь это поможет.

Другие вопросы по теме