Let's say there are a hundred screens in the app and the app is 300mb. Does it really take 3mb of source code, about 3/4 of a bible, to render one screen?
(I do understand that source code isn't what ships in the binary, but for the sake argument let's say they're 1:1 in size.)
Considering that Uber's binary size (330MB) is comparable to similar apps such as Google Maps (224MB), Lyft (435MB), and Didi (332MB), it might just be par for the course for iOS apps.
Yelp, for example, is what you might call a "straightforward CRUD app" (to Yelp engineers, I know it's probably legit complicated and hard), and that is 292MB on the App Store.
It's probably to do with how the framework handles lifecycle management and combining static assets like text and image with business logic that lives in Controllers.
It must be mostly the dependencies and assets they're pulling in for each screen, and not simply the source code. They could be using a different SDK for each type of payment they take, which is a lot. If the app has 250 features, and each feature includes 4MB of assets (images, icons, sounds, etc.), that's already a gig right there. I also suspect that there's a lot of reinventing the wheel going on, since there's 40+ feature teams all working on the app at the same time.
"Reinventing wheels" are represented by the machine-code outlining :)
These are code. Swift is a safe language with more runtime checks than other "zero-abstraction" languages. It also support "value" semantics and can deploy monomorphization for generics (although no guarantee). All these means you can have functions with slightly different view models duplicated many times throughout the binary.
Not to mention the language itself need to generate a lot of retain / releases for refcounting purpose (the blog post also pointed this out).
All in all, Swift as a language is not particularly optimized for small binary sizes, and there are a lot of trade-offs made to improve the usability rather than binary size. That has been said, there can be more opportunities exploited (and right now not) to reduce the binary size from compiler side.
(I do understand that source code isn't what ships in the binary, but for the sake argument let's say they're 1:1 in size.)