Photo by Roman Bozhko on Unsplash

Formatters take data like numbers, dates, times and more and convert it into a localized and user-presentable string.

Because formatters are backed by quite a bit configuration data, a common pattern was to cache and reuse them:

class Meeting {    private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter
func displayMeetingDate(_ meetingDate: Date) {
dateLabel.text = Meeting.dateFormatter.string(from:

It was really easy to forget that this needed to be cached, which lead to re-creating the same formatter again for every element that needed it…

Photo by Braden Collum on Unsplash

In the next articles I will write down my adventure of exploring Core Data in SwiftUI and unit test it.

Create a new project

To understand what’s going on, we will add Core Data manually to the project instead of checking the Use Core Data checkbox in the New Project panel. So start with creating a new Xcode project:

How to develop accessible iOS apps

When a user navigates your app with an assistive technology, the interface is not the same as the one visible on the screen. They navigate a modified version that iOS creates, called the accessibility tree or Accessibility UI (AUI).

The difference between SwiftUI and UIKit is how iOS creates the AUI. In UIKit, iOS builds the visual interface and then generates an AUI from the screen. The accessibility API then combines this with any accessibility modifications you have made in code.

With complex UI or custom components, it can be hard for the API to interpret the experience you intended…

How to develop accessible iOS apps

Photo by Farzad Mohsenvand on Unsplash

An important aspect of making your app accessible is to localize your app. Localization is the process of adapting a product or content to a specific locale or market. This includes translating, but also adapting graphics, content, and layout to suit the tastes and consumption habits of the target markets. You have to convert currencies, units of measure, formats of dates, addresses, and phone numbers to the local requirements as well.

Even if you release an app only in a specific country, keep in mind there are also people in that country that doesn’t have that country’s language as their…

Photo by Thiébaud Faix on Unsplash

As many of you might know UITextField has a delegate protocol to notify you if the text of the textfield changes. But the only method that does that is textField(_:shouldChangeCharactersIn:replacementString:). This method is meant to stop editing and it provides the text before change, the range of the changed characters and what they are replaced with.

Some developers use this method to compute the final text from the parameters of this method. They can’t use the UITextField’s text, provided as a parameter, because the method is called before the actual changes will happen.

But there is an easier way! UITextField

Photo by Graphic Node on Unsplash

Almost in every project I need a view or a button that has rounded corners and sometimes even a bit of shadow at the same time. It can be a bit hard when you start to apply both to the same view.

This is a base class you can use to create a round button with or without shadow. You can make something similar for views:

@IBDesignable class RoundButton: UIButton {   // MARK: - Properties   @IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
@IBInspectable var shadowColor: UIColor = UIColor.darkGray {
didSet {

Photo by Markus Spiske on Unsplash

A bit is the smallest piece of information that can be 1 or 0 (on/off). Eight bits together are called a byte. A UInt8 in Swift is represented by 8 bits. The difference of this unsigned integer with the signed integer Int8 is that Int8 uses 1 bit to signify whether the integer is positive or negative. Having eight bits to represent a number means we can represent 2⁸ = 256 different numbers with UInt8.

0 = 00000000    2 = 00000010    4 = 00000100      8 = 00001000…

Photo by Jason Rosewell on Unsplash

VoiceOver is often referred to as Apple’s screen-reading technology that gives users control over their device without seeing the screen. It is one of the tools used to make an app more accessible. Most people think it only benefits the visual impaired users and that it is a lot of work to implement… But actually both are not true! Experiencing your app through VoiceOver reveals things like copy, order or navigation that doesn’t sound right and this can be an indication that visually it may not read or navigate well either. …

Photo by Jantine Doornbos on Unsplash

The Basics

To decode a JSON structure and encode the model in your app back to JSON, you can conform your model to the Swift Codable protocol. This is a combination of two other protocols: Decodable and Encodable.

This is great for simple JSON arrays and dictionaries like:

let json = """
"name": "Annual Travel Insurance",
"paymentFrequency": "yearly",
"description": "Travel safe all year round."
"name": "Car Insurance",
"paymentFrequency": "monthly"
""".data(using: .utf8)!

You can conform your model to the Codable (or Decodable) protocol:

struct BankProduct: Codable {
var name: String
var paymentFrequency: PaymentFrequency
var description: String? …

Photo by Dmitry Ratushny on Unsplash

When making a network call we need a callback, or so called completion handler, that tells us if our call was successful and returns some data or if something has failed.

The traditional Objective-C approach of completion handlers has it’s shortcomings: it is not clear what you can get back. Data, an error, both or neither of them.

func load(completion: @escaping (Data?, Error?) -> Void) {

The dataTask() method from URLSession is even worse: it calls its completion handler with (Data?, URLResponse?, Error?). So it has eight possible outcomes.

In Swift we can do better. We have generics…

Jeroen de Vrind

iOS Engineer at ABN Amro bank. Author of How to develop accessible iOS apps.

Get the Medium app
