В Swift, как бы я ссылался на «себя» во вложенных таймерах? - PullRequest
0 голосов
/ 24 февраля 2020

Если бы я вложил два таймера, которые оба являются свойствами класса, на который они ссылаются, я должен был бы вызвать [weak self] в обоих или только в первом блоке таймера?

timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
    print(self)
    self?.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
        print(self)
    }
}

1 Ответ

1 голос
/ 24 февраля 2020

Пока вы не конвертируете ссылку weak в сильную вне вложенного закрытия, ссылка weak передается во вложенное закрытие, поэтому вам не нужно делать ее weak снова.

Таким образом, приведенный ниже код вполне подходит:

timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
    print(self)
    self?.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
        print(self)
    }
}

Вы можете подтвердить это тем, что получите неявное выражение

. по принуждению от «Таймеры?» на «Любое»

Для обоих операторов print.

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

Это создает цикл с сильной ссылкой, поскольку для доступа к timer2 вы используете сильную ссылку в self.

timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
    print(self)
    self.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
        print(self)
    }
}

Пока вы преобразуете слабую ссылку в сильную, используя переменную с другим именем, ссылка на self будет weak, и, следовательно, вы не ' снова нужно сделать weak.

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

timer1 = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
    guard let strongSelf = self else { return }
    print(strongSelf)
    strongSelf.timer2 = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
        guard let self = self else { return }
        print(self)
    }
}
...