From zero to the App Store in one week-end

Build a complete app from scratch in a week-end? Challenge accepted! I started the project on Friday evening and submitted the app for review on the App Store on Sunday evening. It was accepted during the night and live on Monday morning.

So what was there time to do in just a weekend? Actually, a lot:

  • SwiftUI: I experimented a tiny bit of SwiftUI before, but nothing compares to building a real app!
  • GPS based location is retrieved in the background, reverse geocoded and stored in CoreData
  • Forms: automatically recording locations is cool, but you sometimes have to go and manually add or edit visits, SwiftUI makes it particularly easy to create dynamic forms with very little code and handles pretty much everything for you
  • In-App Purchase with a paywall selling a non-consumable product to unlock some features like yearly / country reports and PDF export
  • PDF generation from HTML templates, and export using a SwiftUI wrapped version UIActivityController
  • Analytics and Crashlytics integration using Firebase
  • App Store preparation: finding a name, writing description, creating a logo, preparing screenshots, submitting the In-App Purchase product
  • Submission!

What kind of issues did I run into?

  • SwiftUI is fun, but sometimes it’s just really hard to do something really simple (like presetting two modals / sheets from the same view), and sometimes you simply can’t do something simple (like removing the disclosure indicator from list cells without generating random crashes)
  • Fastlane didn’t want to work on my machine, I wanted to automate the screenshots but couldn’t, but it’s ok, since there is only one language for now and the app only support the iPhone, taking screenshots manually wasn’t too long
  • Apple randomly disabled submission from the version of Xcode available on the Mac App Store, and obviously the error message when submitting was super obscure… had to download the next coming GM from the developer download center

Is the code clean? Hell no! But was it fun to do? Absolutely! I don’t know if this app will ever sustain itself, but I’ve to admit we live in a time where very powerful tools are available for us to experiment and iterate really quickly. I’ll definitely do this kind of challenges again 🙂

Link to the app: https://apps.apple.com/us/app/trvl/id1487340379

SwiftUI Ambiguous reference to member ‘buildBlock()’

So this work:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Text 1")
            Text("Text 2")
            Text("Text 3")
            Text("Text 4")
            Text("Text 5")
            Text("Text 6")
            Text("Text 7")
            Text("Text 8)
            Text("Text 9")
            Text("Text 10")
        }
    }
}

But this doesn’t:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Text 1")
            Text("Text 2")
            Text("Text 3")
            Text("Text 4")
            Text("Text 5")
            Text("Text 6")
            Text("Text 7")
            Text("Text 8)
            Text("Text 9")
            Text("Text 10")
            Text("Text 11")
        }
    }
}

The compiler refuses to compile and prompts the following error: Ambiguous reference to member 'buildBlock()'.

This is due to the view building system in SwiftUI internally having code to let you add 1 view, 2 views, 3 views… up to 10 views, but nothing for 11 and beyond.

The solution is to wrap up to 10 elements in a Group, it allows you to break your components structure, for example:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Group {
                Text("Text 1")
                Text("Text 2")
                Text("Text 3")
                Text("Text 4")
                Text("Text 5")
                Text("Text 6")
                Text("Text 7")
                Text("Text 8)
                Text("Text 9")
                Text("Text 10")
            }
            Text("Text 11")
        }
    }
}