At the end of March this year, when the coronavirus lockdown began, I started missing table tennis. I decided to create a mobile app for table tennis players and enthusiasts. I already have a few personal apps and games in the iOSĀ App StoreĀ but I wantedĀ ForehandĀ to be a bigger, multiplatform (iOS and Android) and long term one. Something like a personal business card for a mobile apps developer.
As Iām an iOS developer, I started from an iOS app. Itās 2020, Iām starting a new iOS app, sounds like a great opportunity to learn more about SwiftUI I thought. So I started building the iOS version of Forehand using SwiftUI. It was going quite well letās say, I added a few initial screens.
SwiftUI project structure
First problems that I faced were around a performance of VStack. I had a VStack containing 5 WebView views, each of them loading a different HTML, embedded YouTube video.
WebView which I embedded 5 times (each with a different HTML) in VStack
Putting 5 instances of such a view was killing the performance, VStack was just almost non-scrollable.
Main issue number 2 was customising a navigation bar. Navigation bar on some of the screens was supposed to look like this:
Navigation bar with a custom background colour
or like this:
Another example of a navigation bar with a custom background colour
Unfortunately customising navigation barās background colour or its titleās background colour is not natively supported in SwiftUI and I needed to try some UIKit-ish solutions. None of them was perfect and at some point I even ended up replacing a navigation bar with a normal View. It worked, I could fully customise it but I didnāt feel itās a long term solution. At the end I left default colours.
The last thing that Iām gonna mention in this article about problems with SwiftUI is Onboarding screen. In UIKit we do it with UIPageViewController. Unfortunately there is no built in SwiftUI component for that yet. I researched Stackoverflow what workarounds other developers do, I found a few solutions. They were based on manually calculating frames of swiped views. It didnāt work well for all screen sizes unfortunately so I decided to use a UIKit bridge called UIViewControllerRepresentable. UIViewControllerRepresentable and UIViewRepresentable are protocols which let you embed old good UIViewController or UIView in a SwiftUI app. So I had Onboarding screen working but there was a navigation to the Home screen after tapping a Next button on the last page of onboarding missing. In a UIKit-only app it would be an easy push(viewController) or performSegue(with identifier) but SwiftUI screens are driven by state changes so itās a bit different.
I ended up doing something like this:
I was sending a āNextButtonTappedNotificationā from Onboarding SwiftUI view conforming to UIViewControllerRepresentable and it was being received by ContentView which is SwiftUI appās entry point. Not entirely clean solution but changing screens worked. There was a problem with a navigation bar though. I couldnāt get rid of an additional top header added by NavigationView / NavigationLink. I spent 2/3 evenings on that and taking into account previous problems as well I came to a conclusion that maybe it will be better to wait for SwiftUI 2.0 and not to spend my evenings on being frustrated and trying to fix things that are super easily achievable in UIKit. Thatās why I decided to stop using SwiftUI for the first version of Forehand. I rewrote everything what I had to UIKit views in 2 days and I started progressing with the project much faster.
Most of the mobile applications need some sort of backend, some remote data provider. Forehand is not different. As I am a one-man-band (in terms of devs, because I have an awesome designer working with me on Forehand too), I wanted to go for something easy to set up, integrate and multiplatform (iOS, Android). I considered 2 options: Firebase and AWS. From my previous experience I knew that Firebase is easier to set up, you donāt need to deal with a maze of permissions setup but on the other hand AWS seems to be more scalable. As I think about Forehand as the app that Iām gonna support and maintain for a longer time, I decided to use AWS driven backend for my app. Unfortunately I faced a blocking issue just at the beginning of the integration, at authentication stage. I want the users of my app to be able to authenticate using the following methods: Log in with Facebook, Sign in with Apple and Email + password sign in. Sign in with Apple is not only a nice to have sign in method, but itās also required by the App Store review guidelines if you have any social sign in method (including Log in with Facebook) in your app:Ā https://developer.apple.com/news/?id=09122019b. Even though AWS Cognito officially supports that sign in method as per this article:Ā https://aws.amazon.com/about-aws/whats-new/2019/11/amazon-cognito-now-supports-sign-in-with-apple/, there is still an open issueĀ https://github.com/aws-amplify/aws-sdk-ios/issues/1809Ā and people try to find hacks to make it work. I didnāt want to go that way, I didnāt want to spend my evenings on finding hacks to fix AWS Cognito bugs and thatās why I decided to switch to Firebase where all sign in methods which I needed worked perfectly and the whole configuration process is really well documented.
Conclusions
- Some of you may say that Iāve given up too early and thatās a fair point. I just want my free time that I spend on coding a personal app to be as enjoyable as possible. I also want to see the results as soon as possible, to touch what I build and to let other people touch it, test it, give some feedback.
- Most of the SwiftUI issues that Iāve faced are fixed in SwiftUI 2.0 which will be publicly live this autumn. There are lazy stacks, native support for onboarding-like screens and much more:Ā https://developer.apple.com/videos/play/wwdc2020/10041/. I just didnāt want to wait a few months for SwiftUI 2.0 to be publicly live and then maybe 2/3 months to build my app from scratch using a technology that Iām not fully confident with yet.
- In terms of a backend solution – Iām not forgetting about AWS. Maybe one day I will go for some kind of a hybrid solution: Firebase managed authentication and AWS for storing and providing data – I donāt know if itās possible though. I would need to do more research.
I hope this article will be at least a bit helpful for some of you. Please feel free to share your thoughts and experience with the technologies mentioned here.