Swift

Using UISheetPresentationController in SwiftUI

Published on: June 30, 2021

With iOS 15, Apple introduced the ability to easily implement a bottom sheet with UISheetPresentationController in UIKit. Unfortunately, Apple didn't extend this functionality to SwiftUI just yet (I'm hoping one of the iOS 15 betas adds this...) but luckily we can make use of UIHostingController and UIViewRepresentable to work around this limitation and use a bottom sheet on SwiftUI. In this post, I will show you a very simple implementation that might not have everything you need. After I tweeted about this hacky little workaround, someone suggested this very nice GitHub repository from Adam Foot that works roughly the same...

Read more...

Presenting a bottom sheet in UIKit with UISheetPresentationController

Published on: June 30, 2021

We've seen bottom sheets in Apple's apps for a while now, and plenty of apps have followed this pattern. If you're not sure what I mean, it's the kind of sheet that takes up just a part of the screen and can be swiped upwards to take up the whole screen or downwards to be dismissed. Here's an example from Apple's Maps app: To implement a sheet like this, we used to require third party tools, or we needed to get creative and implement this pattern ourselves. With iOS 15, Apple introduced UISheetPresentationController which allows us to implement bottom sheets...

Read more...

What’s the difference between a singleton and a shared instance in Swift?

Published on: April 19, 2021

A common pattern on iOS, and in Swift, is to define an instance of an object that you can access from any place in your app. Common examples are URLSession.shared, FileManager.default, and UserDefaults.standard. These objects can all be considered shared instances, or globally available instances. Defining a shared instance is commonly done as follows: struct DataProvider { static let shared = DataProvider() // useful properties and methods } It's common for developers to call this a singleton, or a singleton instance. The singleton pattern is a pattern that allows developers to specify an object that can only ever have one...

Read more...

10 things iOS developers should focus on in 2021

Published on: January 4, 2021

I know. This is a clickbaity title. And yes, I know that this list is not relevant for everybody. I know that not every iOS developer has to learn everything on this list. That said, this list is a list of technologies and skills that I think are either already important, or becoming increasingly important this year. It's a list of technologies and skills that I have learned, plan to learn, or would like to learn this year. It's also a list that hopefully inspires you to broaden your horizons, and learn new things. Or maybe this list inspires you...

Read more...

Building a simple remote configuration loader for your apps

Published on: October 26, 2020

Remote configuration is a common practice in almost every app I have worked on. Sometimes these configurations can be large and the implications of a configuration change can be far-reaching while other times a configuration is used to change the number of items shown in a list, or to enable or disable certain features. You can even use remote configuration to set up your networking layer. For example by setting certain headers on a request, providing endpoints for your remote data, and more. In this week's post I will not go into detail about every possible use case that you...

Read more...

Understanding how DispatchQueue.sync can cause deadlocks

Published on: September 21, 2020

As a developer, you'll come across the term "deadlock" sooner or later. When you do, it's usually pretty clear that a deadlock is bad (the name alone implies this) and if you've experienced one in your code, you'll know that your application crashes with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) when a deadlock occurs. A few weeks ago, I wrote about dispatching code synchronously and asyncronously. Several people pointed out that that post does not mention deadlocks. Instead of making that post longer and more complicated, I decided to make this week's post all about deadlocks and understanding what they are. If you're...

Read more...

Dispatching async or sync? The differences explained

Published on: August 31, 2020

When writing iOS apps, we regularly run into code that is asynchronous. Sometimes you know you're writing something that will run asynchronously and other times you're passing a completion handler to code that may or may not run asynchronously on a different dispatch queue. If you're familiar with using DispatchQueue.main, you have probably written code like this: DispatchQueue.main.async { // do something } And while writing this, you may have encountered a second method on DispatchQueue.main called sync. In this week's post I will explain the difference between sync and async, and you will learn when you might want to...

Read more...

Understanding Swift’s OptionSet

Published on: August 18, 2020

Every once in a while I look at a feature in Swift and I fall down a rabbit hole to explore it so I can eventually write about it. The OptionSet protocol is one of these Swift features. If you've ever written an animation and passed it a list of options like this, you have already used OptionSet: UIView.animate( withDuration: 0.6, delay: 0, options: [.allowUserInteraction, .curveEaseIn], animations: { myView.layer.opacity = 0 }, completion: { _ in }) You may not have realized that you weren't passing an array to the options parameter, and that's not surprising. After all, the options...

Read more...

Using Codable with Core Data and NSManagedObject

Published on: August 3, 2020

If you've ever wanted to decode a bunch of JSON data into NSManagedObject instances you've probably noticed that this isn't a straightforward exercise. With plain structs, you can conform your struct to Codable and you convert the struct from and to JSON data automatically. For an NSManagedObject subclass it's not that easy. If your Core Data data model is configured to automatically generate your entity class definitions for you (which is the default), you may have tried to write the following code to conform your managed object to Decodable: extension MyManagedObject: Decodable { } If you do this, the compiler...

Read more...

Setting up a Core Data store for unit tests

Published on: July 27, 2020

Unit testing is an important skill in the toolbox of any engineer. Knowing how to write a reliable, robust test suite helps you write reliable and robust code. If you've followed my introduction to unit testing part one and part two, or if you're experienced with unit testing you know that your tests should run isolated from any other tests. You also know that you should make sure that your test relies on as few external dependencies as possible. When you want to test your Core Data code, it might not be immediately obvious how you can test your Core...

Read more...