A Touch of Something Different —

The Missing Gesture in SwiftUI

Image for post
Image for post

This short paper is based on iOS 13, Swift 5.x; It may work on an earlier version, but I didn’t test; a disclaimer.

The brief was to write a simple game to help his students learn French verbs. A task that is much harder the then it sounds, did you know for example that they’re twenty three different tenses in French, resulting in almost 100 variations of a common verb like avoir “to have”.

The goal to let students choose a verb and a tense and then correctly type in an answer. I ran up a POC in an hour or so with my five sample verbs the professor had given me. But I didn’t like it.

I didn’t like it cause the app needed to run on an iPhone, it was clearly the target platform. The problem the keyboard. Not only do you need nano sized figures to accurate hit keys or indeed surgeon steady hands, but worse the keyboard takes up half my screen when it comes up. I am left with next to no room to present anything.

Adding to my woes, Apple has just launched the iPhone SE; a budget [read popular with students] model with a even smaller screen.

The problem quite a specific one. I had suggested multiple choice. I had asked the professor. Non. ça ne marchera pas. He said was too easy, he needed his students to know the verbs, give them multiple choice — Non.

Could I use a picker wheel full of letters somehow; But no it would look awful. Could I rotate the thing, take up less space maybe. Wasn’t sure if it was even technically feasible, unsure if it would look any better either. I decided to try my hand at building a custom keyboard, now there is a challenge. A side scrolling one. Added to which it might be more fun.

Started with a rectangle and some dragging controls. This code.

Next I added some boxes to represent my keys. The plan was to create a spining wheel of letters. I built this prototype and gave it go. It was awful. Really painful. No that wasn’t going to fly. I needed a touch gesture. I need a way for my student to be able to fly from one end of the keyboard to the other, with one gesture. And no not a swipe. I needed touch.

But this is SwiftUI, not UIKit.

So I turned to SO and found this excellent little piece to start me off. I could use the drag gesture, since that gave me some feedback instantly. So more than a click. But the SO answer I had didn’t implement touch, it looked more like a tapGesture. I sat back in my chair and considered my options. I like SwiftUI, I was going to make it work with SwiftUI.

I played around with some ideas, nothing worked. I tried all the SO answers, they all looked like the tapGestures in the end. What I needed was a gesture that would start, and repeatly fire.

The answer of course was with Combine framework with a secret ingredient, no really, with a timer. I added two publishers to my drag gesture. One would fire when I started to drag, one would fire when I stopped. Most importantly, the one that fired when I started… would keep firing.

With this in my main loop.

The timer the tunning mechanism for controlling how quickly or slowly my repeat would work.

Of course there are few variables in here and enum to keep those nasty magic numbers out, but don’t worry cause I am give you the whole shebang at the end of the paper.

This from a touch point of view worked perfectly. I touched it moved… it continued to move until I left go. It was good, it works like touch — But it wasn’t intuitive, no I relised needed my drag back.

I tweeked a little, added a onTapGesture and ended up this… the whole shebang here. It works well, just a little differently.

Now when you scroll left, it starts and continues — when you tap it stops. Just like a real wheel. Stay calm and keep coding —

Written by

Coding for 35+ years, enjoying using and learning Swift/iOS development. Writer @ Better Programming, @The StartUp, @Mac O’Clock, Level Up Coding & More

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store