Unpopular opinion: assertions are great, but should only be used for problems that cannot be detected immediately at runtime.
E.g. there’s no need to check that an Optional is non-nil before force-unwrapping it, or that an index is contained within the bounds of a Collection; the Swift runtime is _guaranteed_ to trap for these. All you’re doing is adding clutter.
And obviously the best strategy remains to architect your code so that you don’t have to force-unwrap or access unsafe indices in the first place — but in these rare situations where you have no choice *and* an explanation is not warranted, assertions are clutter.
@layoutSubviews combining the 2 posts above, I'd say assertions are useful for the in betweens. eg. when you import code/library, you use asserts (preconditions right?) so your own code is clean

@layoutSubviews But assertions only halt in debug mode not in release so they are useful where something should never happen but you can defensively program in case it does.

So combine assertions with nil-coalescing for optionals or catching errors.

@JosephLord @layoutSubviews exactly my thoughts. I do a “fail early and often, but not on production”.
So I use assert + log + safe fallback, and it has worked quite well.
@layoutSubviews That is unpopular, indeed. Using force unwrap in the first place, and not using the message of the assert, which is all about *why* you don’t expect the thing to happen.
(and then, asserts - unlike fatals - only fire in DEBUG, ie do sth pretty different. they lead to more robust code design dealing w/ unexpected situations, unlike forces, which always make your app just crash)