Prevent background view from being resized when using iOS 13+ default modal presentation

This simple trick helps preventing the system from resizing the background view when the modal appears. It keeps the standard behavior (panning view, partial view with dark veil) but leave the background view untouched.

Simply set the following flag on your UIViewController, for instance inside the viewDidLoad method:

definesPresentationContext = true

If the presenting view controller is a child of a navigation controller, then we need to apply this flag to the navigationController instead of self:

navigationController?.definesPresentationContext = true

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

Detecting first launch, app upgrades and other useful launch informations

One of the first things every iOS developer should add to their project is a way to detect what is happening at launch. It doesn’t have to be complicated, but trust me, this can potentially save you some trouble later on.

I usually create a BaseAppDelegate class that will be responsible for detecting the following:

  • is it the first time the user launch the app?
  • how many times did the user launch count?
  • is this launch the first launch after an app upgrade?
  • when was last time the user launched the app before this launch?

Here is the code I usually put in this BaseAppDelegate class:

https://gist.github.com/cyrilchandelier/e66f003c2b116482243f3778c675b82a

You just need to make your AppDelegate extends BaseAppDelegate, and call the super method in application(_:didFinishLaunchingWithOptions). Then, you can choose (or not) to override (and therefore implement something for) the applicationFirstLaunch() and/or applicationDidUpgrade(from:to:) methods.

Here are a couple use cases where having this super-class reveals itself handy:

  • I want to know how many times a users came into the app for my analytics
  • I want to know when a users re-open the app after a while, to customize his experience as a returning user
  • I want to show a “What’s new” popup to my returning users who upgraded their app
  • my app was a paid app before, and now it’s free with In-App Purchases to unlock some content, but I don’t want my users who already paid to hit my paywall