The Chat Screen That Never Closed
#ios-crash-reports — jetsam kill after opening 10 chats
Crashlytics: 847 users terminated by memory pressure. Each chat leaks ~45MB. ChatViewController + ChatViewModel retain cycle — strong delegate and closures capturing self.
The trap: VC owns VM · VM delegate points back strongly · stored closures capture self strongly · neither deinits.
Your task
Fix `ChatScreen.swift`: weak var delegate, [weak self] in Timer and stored closures in `ChatViewModel_Fixed` and `ChatViewController_Fixed`.
Book: ARC just works · Prod: 450MB leaked after 10 chats → iOS jetsam.
Skills you'll prove
Interview Tip
When asked about ARC or memory management, say: "The most common retain cycle in iOS is between a ViewController and a closure. The VC owns the ViewModel. The ViewModel holds a closure. The closure captures self (the VC) strongly. Now neither can deallocate. The fix is two-fold: make delegates weak, and use [weak self] in every closure that outlives the call. I once fixed a chat app where every chat screen leaked 45MB — after 10 chats, iOS would kill the app for memory pressure. Adding weak in 3 places eliminated the leak entirely. My rule: if a closure is stored, always use [weak self]."