반복 Timer 블록에서 옵셔널을 없애려고 [weak self]를 [unowned self]로 바꾸고 화면을 닫았어요. 다음 틱에서 크래시가 났어요.
이상할 건 없어요. 런 루프가 예약된 타이머를 살려 두고, 타이머는 자기 블록을 쥐고 있어요. 그래서 누가 invalidate()를 부르기 전까지 클로저는 컨트롤러보다 오래 살아요. unowned는 컨트롤러가 클로저보다 오래 산다고 Swift에 말하는 건데 여기서는 정반대고, 해제된 뒤 unowned 참조에 접근하면 런타임 오류라고 책에도 분명히 나와요.
강한 캡처는 크래시가 나지 않아요. 대신 더 조용하게 나빠요. 타이머가 블록을 쥐고 있는 동안 컨트롤러가 사라질 수 없으니, deinit에 넣어 둔 invalidate()가 영영 실행되지 않고 타이머는 계속 돌아요.
제대로 되는 건 weak인데, 그래도 정할 게 남아요. 이 콜백이 소유자를 계속 살려 둘 이유가 있나요? 없어요. 그럼 소유자 없는 틱은 무슨 뜻일까요? 여기서는 아무 뜻도 없고 타이머가 멈춰야 해요. 그래서 deinit이 invalidate()를 부르고, guard let self else { return }은 값싼 확인으로 남겨 둬요.
