As long as fallible humans are involved in creating software and hardware we will have bugs, and some of those bugs will be exploitable.
The best we can hope for is using the best tools and practices we have available to make it as hard as possible to make mistakes and therefore as hard as possible for attackers to find exploitable bugs.
In reality tho, that's not really what happens. We still use C (and C++) for example (and other footgun-languages) and/or run billions of lines of badly audited "legacy" code (that wasn't written with the threats we face today in mind) in a lot of places for various reasons[0], and then try to use all kinds of tools as work around to detect past and new mistakes or at least mitigate the severity of outcomes when mistakes happen and are uncovered and exploited by adversaries[1].
And that's not even yet considering supply chain attacks, be it software or hardware ones.
That isn't to say that Apple couldn't still do a lot better...
"Beware of bugs in the above code; I have only proved it correct, not tried it."
[0] Such as maintaining legacy code bases, "performance", interoperability, development speed, developer availability, business ("cost") considerations, etc.
[1] Starting with code reviews, code coverage, unit tests, static analysis, fuzz testing, etc, and then later at runtime ASLR, canaries, retpoline, sandboxes, etc.