I've just spent the last year working both as a mobile application developer and working on a side project building a totally cross-platform video game from scratch in C. It's an odd juxtaposition. In my side project, I fully expect that the code I write will run on a Mac, Windows, a Sony Playsation whatever you like.
But with mobile apps, I often start with one platform and labor under the expectation that much of the code I write will have to be written again by someone else on another team who is more familiar with Java or Kotlin (since it is practically impossible to make employers believe that a single human being can be just as competent with multiple platforms).
I can't help but ask a simple (if not totally naive) question.
Why is this the case? Why isn't the mobile world doing the same thing the game industry does?
Why don't we put the cross-platform logic into a shared C library and simply have the separate platforms call into it?
We often preach that duplication is a bad thing. If the app uses the same layout on the iPhone as it uses on Android, wouldn't you want some shared representation of that layout? Wouldn't it make sense to remove the duplication and therefore maintain less code on both platforms?
What follows is not necessarily me advocating a particular approach or answer to this question. It's more of a free form exploration taking what I've recently learned into account. I simply want to pose the problem and see where that goes while comparing and constrasting some tools I have used to build apps in the past.
Games differ from most mobile apps in some pretty significant ways. I want to highlight them quickly and demonstrate why that leads to certain design decisions.
Most games use totally unique graphical assets and user interfaces. They do not borrow from some pre-existing design standard that Apple or Google pushes. They are art. They create their own reality.
Most games need to consider performance to a greater extent than mobile apps.
Most games will ship to more platforms than a mobile app, which usually only ships to the two dominant plaforms (iOS plus Android, and usually in that order).
These three factors conspire to make cross-platform lower level programming in C a reasonable decision for most video games.
Mobile apps face a different reality. Most of them don't have totally custom user interfaces. They need to adopt whatever standard Apple or Google encourages, and this usually means the fastest path to getting that "appy" look and feel means adopting one or more of Apple or Google's software development kits.
Sure, you could do all of that drawing and design yourself but you would be more or less copying a ton of pre-existing work (which is not to say this is necessarily bad but to simply point out that the convenience is tempting to most. I hesitate to say "reinvent the wheel" because most software is so broken that we definitely don't have anything so simple and functional as a "wheel" to "reinvent" but the phrase does come to mind).
I don't know of a single iOS developer who doesn't use UIKit for their apps. I'm not even sure it is possible to not use it, even if you're just using it to create a single window into which you do all of your own custom drawing. Of course to even suggest such a thing is considered blasphemy in most mobile app development circles, so there is an obvious cultural hurdle we would have to clear as well.
In any case, even if you are doing all of your own drawing, the mobile SDKs are still your conduit into the operating system on both platforms, so you can't totally ditch them even if you can magically cause a massive change to the culture. Apple and Google will release new features with regularity, and you get those features from adopting at least some of their tools.
When I make a game, I create a single shared cross-platform C library and a small thing called a "platform layer" that calls into that library and grabs a frame of video every 16.67 milliseconds.
When I make an app, I do most of my layout and logic inside of platform-specific languages and tools (Swift and Interface builder for example).
In games, the platform-dependent code is thin. In apps, it is thick.
That's not to say there can't or shouldn't be cross-platform logic in apps. There clearly is. But since we try to leverage so much of what the native SDKs do, we end up relying way more on platform-specific apis than we would in some other context.
In principle, I like some of the ideas behind React Native. I do think mobile app development should try to be cross-platform. There are clear and obvious gains to be made from such a thing, as can be witnessed in the game industry.
That said, I disagree with React Native's rather dogmatic approach to state management and "everything must be a functional component" approach.
Generally speaking, React Native's model is completely at odds with the way the native SDKs actually work. It tries to paper over these differences but in the process only adds more complexity and confusion.
App-wide navigation, in React Native, has to be conceived of as a react component that responds to state changes. It has to be functional.
But that's not how navigation actually works in any of the native SDKs.
Reality is more imperative. In UIKit (Apple's framework), you have a Navigation Controller that manages some screens. You tell it you're ready to go to the next screen, so it puts that screen on top of a stack. It's managing a stack of screens, not reacting to some immutable state. React Native's paradigm doesn't match Apple's and you're basically fighting it the whole time.
It seems to me that many of these popular cross-platform frameworks can't just do the cross-platform thing without also being ideological about whatever programming paradigm they're trying to push.
Just because you bought some furniture from the Amish doesn't mean you reject all pre-1800s technology. It simply means you like a chair.
It would be great if we got all of the cross-platform goodness in React Native with none of the "everything must be functional" ideology. It would play better with the native SDKs, and we would make products that feel more like real native apps.
Most development shops cluster into two camps. There are shops that go full native and create totally separate teams for each platform, and there are shops that try to use some kind of third-plarty cross-platform framework like React Native.
I have never encountered a shop that does their own flavor of cross-platform. In practice, this could mean a number of different things. It could mean sharing common sets of data between the two apps, a common code base, a common build process, heck even a common XML document with all of the server endpoints in it. It doesn't always have to mean sharing code.
I don't think mobile app development will ever be as fully cross-platform as game development. To put it bluntly, we just aren't doing enough from scratch to make the proposition worthwhile for most of the development effort. We rely too heavily on the various SDKs, hoping to save development time by having Apple or Google do most of heavy lifting for us.
And you would have thought the current time savings would be enough. Compared to game development where you're writing your own low level renderer to draw triangles, the cost savings seem enormous.
So why didn't we just stop there and call it a day? Why the push for higher level tools like React Native? Aren't we doing a good enough job of avoiding unecessary work?
Is it possible that, in our quest to avoid work, we are actually creating more of it?