The problem is, the timer creates a strong reference to 'self'. So 'self' will never become deinitialized if it also has a strong reference to the timer. Remember, two objects that both have strong references to each other will never get deinitialized.
There's a few ways to solve this:
1. Don't call invalidate() on the timer in the deinit() method, because that won't get called UNTIL the timer has been invalidated. Instead, call deinit() somewhere earlier in the program, for a view controller you would call it in viewWillDisappear() (keep in mind you will need to re-initialize the timer in viewWillAppear() since the user may navigate back to this VC).
2. Pass a
weak reference to 'self' when you initialize the timer. It would look like this:
Code:
weak let weakSelf = self;
var testTimer = Timer.scheduledTimer(timeInterval: 0.1, targret: weakSelf, selector: #selector(self.testTimerFired), userInfo: nil, repeats: true);
3. There are others but those are the two most common solutions I use. Memory management in Swift is still a pain, but it is still worlds better than pre-ARC Objective-C for sure. A piece of advice is to always put logging statements in your timers, at least at the start, to make sure they are getting called when you
think they're getting called, and AREN'T getting called later on. This has saved my bacon many times when I was starting out in iOS development.