Native vs Cross-Platform Apps
App development has always had this hurdle - to support the vast majority of users, you need to write two apps - one for iOS, and another for Android.
- iOS apps are developed with Swift, or Objective-C, using xCode on a Mac. They target a small set of devices completely under Apple’s control, though the different iPad and iPhone sizes have complicated that a little.
- Android apps are developed with Java, or Kotlin, and can be built via any desktop OS. They target a wide range of extremely varying devices.
The requirements are for someone to need to use two different languages and IDE’s so it’s no wonder stacks such as React Native and Xamarin attract attention. A lot of developers choose not to use a Mac, which means they could build the rest of the app for Android, then fiddle about on another machine in the office at the last stage to get it working for the iOS build (whilst probably reminding everyone of their disdain for the OS, admittedly).
I’ve mentioned before that programming languages themselves are no barrier to a competent developer. There are syntax differences, but they are all trying to do the same loops, conditions and other typical paradigms. The learning curve is more in the environment itself, and what libraries, tools, frameworks and support of such are available.
With native app development, you get the tried and tested tools and direct access to the native API’s. Granted, there are dubious releases which raise a few headaches, but overall you can predictably produce an app and get it to market. The story was much different when writing a React Native app recently:
- Install react-native and tools via npm.
- Start writing the app. Cannot see debug information because Chrome's CORS is blocking. I see others have had this problem but the comments essentially lead to a closed GitHub issue...
- Wade through various stack overflow comments and GitHub issues and find a workaround. It involves running Chrome without CORS enabled, which makes me very uneasy. I am able to see the log output in xCode, if I allow xCode itself to build and run the app, however.
- Install a library to interface with ARKit. Hope it does what I need it to do, as documentation is rather non-comprehensive.
- Install failed. Find out something is temporarily broken in npm and I need to install yarn to install this package. It works, and I get a working demo.
- Carry on developing. Try to debug, but Chrome still cannot see the logs due to a networking issue. Restart devices, set DNS to 18.104.22.168, still no luck.
- Install the React Native debugging tool and launch. Its unable to see the output from the device, and THEN find out in the same docs further down that React Native is not supported yet. Yet someone recommended this...
- Try running react-native log-ios, which should “just work”. Nothing.
- Realise it all works if I use a device simulator, but the app requires API’s which need a real device. Give up.
The story was much different just months ago, where all the tools and npm worked without much to complain about. Something has happened which has thrown everything off, but the kicker is, this was no surprise to me. The entire development environment is very immature and subject to change. At the time of writing, React Native is version 0.53. To expose native functionality of the target devices requires relying on the community to have produced such libraries and hope they include parts of the API’s which you need. I found this to be extremely hit and miss (again, no surprises there). This is an unknown and uncontrollable third-party quantity - dangerous to be making promises to the client with.
The same app took less than an hour to get to the same place using the native tools because they are tried, tested, and officially supported. What’s more, the concept I needed to develop was trivial to implement. Swift isn’t my bread and butter language, but it's not that different to other languages - there are enough demos and samples to get an idea for what to expect, and it was then a case of writing code, seeing what the IDE complains about, and adjusting as necessary.
Android was a similar story but just had more steps to it.
Just one language?
Write once, run anywhere?
React Native disputes this point themselves. It is not write-once, run-anywhere. You share most the business logic of the code, but each platform ends up needing its own separation. I am mentioning this anyway, as it is always one of the first advantages someone gives to using React Native.
Xamarin had the same concept. It uses one code base for the very common tasks but quickly ended up needing the codebase to be split in places.
With Native, you write two apps which doubles the budget...
You write two apps, but you solve the business model once. Writing one of the apps first means the concept and logic is proved in one environment. Any server-side API's are produced and tested with the first app too. Any data models, logic, and functionality is built on the one and any problems are surfaced and ironed out. Writing the second app is a much quicker process as you are porting something that you know works, and is fresh in your mind from weeks (or months) of development.
React Native allows web developers to build apps without retraining
Web developers are in better luck with Cordova, Meteor, etc as these produce apps which are HTML wrappers. In this situation, there is a risk that the developer will not know the usability guidelines which can quickly result in an app being rejected from the app store. Still, if for some reason they restrict themselves to the web stack, then they are limited by the scope of third-party plugins.
Over the years, a few developers have questioned why I’m “still" using Native, or why I would "extend" client budget by writing two apps when we can use Meteor, or React Native, or whatever cross-platform tool comes out next year. Whilst I was tempted to jump ship, the recent exercise simply reminded me why - because I cannot say to the client that their project will be stable and supported for the long term. I am yet to see a cross-platform app project which has not gone significantly beyond timescale and budget.
Using non-release tools to build production software is asking for trouble. If it’s not re-factoring half-way through development because the stack changed their front-end library, it’s 6 months after release when new functionality is needed but the development environment needs all sorts of broken changes before work can begin. This is not a fault of the authors of the stack, but more a case of trying to move into a property when the building is still being put up and then complaining that the electricity isn’t working.
If any of these tools claim a stable release and a solid proven user base then I’ll take another look. For now though, Native is my choice.