I see two parts to your excellent question. One practical. One more based on intent and spirit.
On the practical side iOS developers use all the same techniques others user when writing software. OO, abstraction, encapsulation, modular programming, decomposition, refactoring (though the tools aren’t there), and on more advanced teams continuous integration with a smattering of TDD when possible. Some also make heavy use of acceptance testing frameworks like Frank (a Cucumber-esk inspired by Selenium).
And like Kent Beck insightfully said when he wrote the first version of JUnit: “If it isn’t easy, developers aren’t going to do it.” (paraphrased).
So what do iOS developers do when they can’t unit test? (Now we are getting into the second part of my answer).
They do whatever it takes.
That is there ‘toolkit’.
They ramp up their manual testing.
They write automated acceptance tests.
They spend hours testing, tweaking, simulating, every possible thing that can go wrong on a mobile device (lots can go wrong).
They sweat and agonize over the placement of individual pixels.
Almost none of which can be solved with a ‘unit test’.
I know how you feel.
I would have asked the exact same question myself a year ago before I had gotten into iOS development.
All I can say to those how remain skeptical is to go and build an iOS app yourself and report back your findings.
That’s all I am doing here. I found I couldn’t work the same way I did before.
And while that was initially frustrating, I also began to see how limited my view of quality was, and how much bigger it was than my narrow set of ‘practices’.
That doesn’t mean my practices were bad. I feel they are very good.
It just meant I had to adapt how they were applied. And maybe pick up some new ones along the way.
I think the iOS community could learn a lot from practices pioneered in the Agile community around writing quality code.
I also think the iOS community has a lot to teach the Agile developer community about quality. Especially beyond the code.
Cheers - Jonathan