Marc Prud’hommeaux left the Swift Android workgroup to work on Rust. He helped create Skip, which lets you write Swift and SwiftUI for iOS and Android. His new project, Day, uses Rust to share app logic and UI across mobile and desktop platforms.
His argument is largely about portability and getting beyond Apple’s tools. AI makes a language’s friendliness to human programmers less important to him.
I agree with that part. But for mobile apps, it takes me somewhere else: I’d rather write Swift for iOS and Kotlin for Android.
We can go lower. Should we?
If the reason to use Rust is a performance gain that matters to the app, I’m all for it. Agents make low-level code more approachable. They can help write assembly too, if we really want to go there.
I’m not volunteering to write a settings screen in assembly.
There are still trade-offs. Rust doesn’t automatically make an app faster than Swift or Kotlin; the workload and implementation matter. Going lower also leaves us with code to verify, build tools to maintain, and platform APIs to connect to.
Having an agent write that code changes the cost. It doesn’t make the cost disappear.
For most of the app, I’d prefer the languages and UI frameworks the mobile platforms already support directly: Swift with SwiftUI, Kotlin with Compose. Let each app use its own APIs and behave the way its users expect.
If AI makes porting easier, maintaining 2 native apps seems more reasonable to me. I don’t have to choose a shared framework just to avoid writing the same feature twice.
I’ve complained about cross-platform integration before. That was in 2017, so it says more about my baggage than today’s React Native. Still, I’d like a good reason before adding another layer.
The logic I’d still share
Both apps should give the same answer, but that alone wouldn’t make me extract a shared core.
Take a portfolio calculation. Working out an allocation percentage is simple enough to write in Swift and Kotlin. I’d keep it in both places. The same goes for a small set of rules that’s easy to maintain, especially if it rarely changes.
Sharing starts to make more sense when that grows into substantial business logic: fee calculations, rounding rules, account-specific exceptions. If those rules change often, and each change needs to reach both apps, keeping 2 implementations in step becomes recurring work. That’s when writing and updating the logic once could be more efficient.
A shared core gives that logic a small boundary: pass in the data, get back the result. Calculations, parsing and business rules are good candidates because they don’t need to know which phone is calling them.
Rust could do that job, with UniFFI generating the bindings for Swift and Kotlin. The screens, permissions, camera access and background execution can stay native.
For the simpler functions I’d keep native, shared test cases might be enough: the agent writes each implementation, and both run against the same inputs and expected results. That catches disagreement on the cases we’ve covered, though it doesn’t prove the implementations are identical.
So my default would still be 2 native apps. I’d extract a shared Rust core when the logic is substantial enough, and changes across both apps often enough, to justify maintaining another language and toolchain.
I can live with 2 codebases. I’ve got help now.