Local (nested) functions which capture variables can also introduce allocations (and I suppose the same applies to closures).
Those captured variables need to exist in a heap-allocated box rather than the stack, in case a reference to the function escapes. Unfortunately the compiler sometimes fails to prove when it doesn’t escape, meaning innocent-looking code might be allocating boxes.
I just tracked down 2 of those issues in a project I’m working on. Moving the nested functions out led to slightly uglier code, but this code was in the hot path (that’s why I took care to avoid excessive allocations), so that minor reorganisation cut overall execution time by almost 50%.
All of which is to say: I wouldn’t use Swift for real-time programming as it is today.