Swift Combine. Отказаться от утечки памяти? - PullRequest
1 голос
/ 13 января 2020

Я думаю, что обнаружил утечку памяти, связанную с оператором debounce Swift Combine. Это либо утечка, либо я делаю что-то совсем не так. Вот простой пример, воссоздающий проблему:


    @IBOutlet weak var currentValueLabel: UILabel!

    var numberSubject = CurrentValueSubject<Int, Never>(0)
    var bag = [AnyCancellable]()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupSubscription()
        bag.removeAll()
    }

    func setupSubscription() {
        numberSubject
            .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
            .sink { [weak self] in self?.currentValueLabel.text = "\($0)" }
            .store(in: &bag)
    }
}

Простое использование оператора debounce, похоже, вызывает утечку malloc (проверено с помощью отладчика памяти):

Leak with debounce

Обновление setupSubscription() для отбрасывания debounce, похоже, исправляет это:

    func setupSubscription() {
        numberPublisher
//        .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] in self?.currentValueLabel.text = "\($0)" }
            .store(in: &bag)
    }

Если вы запустите эту модификацию и дождитесь представления чтобы загрузить, (иначе для подписки произойдет, а затем для ее удаления из массива), вы заметите, что утечки больше нет. Утечка волшебным образом исчезла.

Может кто-нибудь сказать мне, если я делаю что-то ужасно неправильно? Для меня это похоже на ошибку.

Спасибо!

1 Ответ

1 голос
/ 13 января 2020

Управление памятью в режиме отладки в симуляторе, отслеживаемом с графиком памяти, не очень реально. Я попробовал это с прибором на устройстве, и я вижу одну утечку mallo c 16 байтов. На мой взгляд, не стоит потеть мелочи, а это очень мелочи. Вы можете сообщить об этом в Apple, если хотите, но не волнуйтесь, будьте счастливы.

...