It’s very simple, as it should be.
- The app doesn’t collect any data
- The app doesn’t do any tracking whatsoever
It’s very simple, as it should be.
The past few weeks I have been working on a iOS application for kids to learn to read the clock. So today, I’m really excited to announce that Clockwise – Learn to read the clock is available in the App Store!
I already had the idea for a while to create an educational app for my 3 kids, but because of the Covid19 pandemic, I finally decided to have a go at it.
The game has been made in Swift 5.2 & Apple’s SpriteKit framework. The books of Paul Hudson (hackingwithswift.com) were really helpful as I did not have any experience a few months ago with SpriteKit.
Go ahead, download Clockwise, and let me know what you think!
In most cases a View Controller shows one screen to a user, but the user can interact with the screen in multiple ways. Every one of these interactions is handled differently in code. This can be through delegation, target-action, notifications, callbacks, …
For example, take the Travelplanner screen of the Reisplanner Extra app I’m working on.
Location Picker
is presented when the row is pressedLocation Picker
is presented when the row is pressedDate Picker
is presented when the row is pressedNow toggle button
can be in an on/off/automatic
state and changes the behavior of the time rowTravel Options
screen is presented when the button is pressedAs you can see, there are a lot of interactions (and there are actually even more interactions for different states of this screen), and all of these interactions need to be handled in code.
In most cases you’ll end up with all kinds of different methods handling these cases, but over time it can start to become unclear where to look when something needs to be changed or added inside your View Controller.
When a (new) team member has to work in the codebase that he has never touched before, it can take some time to find his/her way and know where to look. So how do I try to streamline this?
Every interaction on the screen, triggers something, and I model all these interactions in a Swift enum called PerformAction
.
The enum for the TravelPlanner screen looks like this:
enum PerformAction { case fromLocationRowPressed( location:Location? ) case toLocationRowPressed( location:Location? ) case switchLocationButtonPressed case departureArrivalRowPressed( queryType:TravelTimeQueryType, date:Date ) case nowButtonPressed case travelOptionsButtonPressed case widgetDirectTo_optionsButtonPressed case widgetDirectTo_configureAddressButtonPressed case widgetDirectTo_selectLocation( location:Location ) case widgetCiCo_optionsButtonPressed case nothing }
This enum is added as a nested type inside the TravelPlannerViewController
, so you can reuse the same PerformAction
enum name across your files without getting name collisions.
class TravelPlanneViewController: UIViewController { enum PerformAction { ... } }
If a new member starts reading through your codebase, he/she can check this enum and see at a glance what all the different actions are for this screen.
To react on these interactions, we create a property performedAction
and add a didSet
property observer.
var actionPerformed:PerformAction = .nothing { didSet { switch actionPerformed { case .fromLocationRowPressed( let location ): presentLocationPicker( location: location ) case .toLocationRowPressed( let location ): presentLocationPicker( location: location ) case .switchLocationButtonPressed: switchLocations() case .departureArrivalRowPressed( let queryType, let date ): presentDatePicker( queryType, date: date ) ... } } }
Proxying
Now you have 1 point of entry to handle all your interactions and call your methods.
@IBAction func fromLocationPressed( _ sender: UIButton ) { actionPerformed = .fromLocationRowPressed( location: fromLocationRow.location ) } @IBAction func switchButtonPressed( _ sender: UIButton ) { actionPerformed = .switchLocationButtonPressed }
When using RxSwift I use a PublishSubject
to keep track of changes.
// Create the subject to keep track of the performed actions private let performedActionSubject = PublishSubject<PerformedAction>() // Add a new action to the stream performActionSubject.onNext( .travelOptionsButtonPressed ) // Get updates when an action has been performed viewModel.outputs.actionPerformedObservable.subscribe(onNext: { [weak self] (performedAction) in switch performedAction { case ... } }).disposed( by: disposeBag )
This is not a technique I use for a screen with only one or two actions. I tend to model it like this, if there are a lot of interactions.
The downside is you’ll get a bit of extra code, because you proxy your interaction handling to the PerformAction
enum.
The benefits are
For newcomers (or your future-you) it will be easier to get around the code.
If you enjoyed this post, follow me on Twitter @thenerd_be
It often occurs while writing code that you need to assign a value of a certain type, based on the value of Boolean. To do this there are multiple ways, but the 2 most known are
let isAWildBoolean = true // Set the value of `offSet` to a value based on the Boolean let offSet:Int if isAWildBoolean { offSet = 10 } else { offSet = 20 }
I don’t like the first approach, because it creates a bloated codebase. A better way is to use the ternary operator (also known as the inline-if).
You specify the Boolean you want to evaluate, add a question mark, followed by the value if the Boolean is true, followed by a colon, followed by the value if the Boolean is false.
Continue reading Swift Snippet : Map Bool values with Generics in Swift
A few months back I published a blog post about how to integrate Unity3D within a native iOS application. This tutorial was written for Xcode 6 & Unity 4 and in the comments there were a lot of requests for a new tutorial.
Tonight I found the time to make the video tutorial on how to integrate Unity 5 in a native iOS app with Xcode 7, so I hope you enjoy it!
Continue reading Integrate Unity 5 in a native iOS app with Xcode 7
Apple added a touch-sensitive layer to the screen of the brand new iPhone 6s (plus). With the coming of this new screen, they’ve added some new UI interactions like application shortcuts and peek and pop.
In this 3D touch peek and pop tutorial I will learn you how to implement this new way of interacting with your content by building a photo gallery. When you press hard on the screen you’ll see a preview of the image and if you press really hard the preview will pop into a detail view.
At the end of this tutorial I’ll show you how to add preview actions. This way you can interact with the content without going to the detail view. You can do this by swiping up while you are previewing the content.
Continue reading 3D touch peek and pop tutorial for your Swift application
With the introduction of the iPhone 6S (plus), Apple added a pressure-sensitive layer to their screen. This creates a bunch of new UX possibilities for creating apps. It’s possible to do a hard press on an application icon and get shortcuts which take you to a specific point in your app. For example, if you do a hard-press on the Photo’s app icon you can quickly search for an image, check the most recent images or see your favourites. It’s also possible to make these quick actions dynamic, meaning that you can add and remove actions based on the state of your application.
In this tutorial I will show you how you can add these quick actions to your application icon.
Update: I’ve created a new tutorial for Xcode 7 & Unity 5.
Last year I published a blog post about how to integrate Unity3D within a native iOS application.
Last week I found a better way to integrate Unity3D within a native iOS app, which also eliminates some issues with my previous version. Because it’s quite a long explanation to do and I noticed in my previous blog post that not everything was crystal clear, I’ve made a video tutorial how you can achieve this.
Continue reading A better way to integrate Unity3D within a native iOS app
For a project I needed to add a UIPickerView with custom cells using AutoLayout. UIKit allows this via the UIPickerViewDelegate method pickerView(_:viewForRow:forComponent:reusingView).
The cell just needed an UIImageView and UILabel, so I thought it would be pretty straightforward to do, but there are some caveats you need to know. Big thanks to Tom Adriaenssen for pointing them out and not ruining my Sunday afternoon 🙂
Continue reading Custom cells for UIPickerView with AutoLayout
Too many times a client has asked to add a sliding image gallery to an iOS app, so I wrapped it up in a little component. You can download it from GitHub.
I took some time to write this component, so it is easy to manage image slider galleries. First I looked around on the web, but there was nothing that really fitted my needs, so the best thing to do in such a case is write it yourself :-).
You can download the project on GitHub. If you have any questions, just ask it on Twitter, put a comment below or open an issue on GitHub.
The component is also available via CocoaPods.