Recent articles

Jump to a random post

Using try catch in Swift

Published on: February 24, 2020

In Swift 2.0, Apple introduced the throws keyword in Swift. This addition to Swift language added the ability for developers to write code that clearly communicates that an error might occur during the execution of a code path, and it forces the caller of that code to handle, or explicitly ignore the error in-place. In this post I will show you what the throws keyword is exactly, and how you can deal with errors in your codebase. Working with code that throws errors If you've worked with JSONDecoder in Swift, you have already experienced code that can throw an error....

Read more...

Adding default values to subscript arguments in Swift 5.2

Published on: February 19, 2020

The ability to define custom subscripts in Swift is really powerful. It allows us to write very natural and concise code. Consider the following example of a Grid with a custom subscript: struct Grid { let items : [[GridItem]] subscript(x x: Int, y y: Int) -> GridItem? { guard !items.isEmpty, (items.startIndex...items.index(before: items.endIndex)).contains(x) else { return nil } let row = items[x] guard !row.isEmpty, (row.startIndex...row.index(before: row.endIndex)).contains(y) else { return nil } return row[y] } } Note that subscripts don't use labels by default. To make a subscript use labels, you need to manually declare the subscript label twice like I did...

Read more...

How and when to use callAsFunction in Swift 5.2

Published on: February 17, 2020

A new Swift 5.2 feature is the ability to call instances of types as functions. Or, as the Swift Evolution proposal calls it "Callable values of user-defined nominal types". The very short description of this feature is that it allows you to call instances of any type that has a callAsFunction method implemented as if it's a function: struct InvestmentsCalculator { let input: Double let averageGrowthPerYear = 0.07 func callAsFunction(years: Int) -> Double { return (0..<years).reduce(input, { value, _ in return value * (1 + averageGrowthPerYear) }) } } let calculator = InvestmentsCalculator(input: 1000) let newValue = calculator(years: 10) While...

Read more...

Testing push notifications in the Simulator with Xcode 11.4

Published on: February 12, 2020

For years we've had to resort to using physical devices when testing push notifications. With Xcode 11.4, Apple finally gives developers the tools needed to test push notifications on the iOS Simulator. I'm going to assume you already know how to add push notifications to your app. If you've never added push notifications to an app before, I have a post that describes how to set up and test push notifications without a third-party service. That post should get you all set up to follow along with this post. Sending a test push from the command line Xcode comes with...

Read more...

Using Promises and Futures in Combine

Published on: February 10, 2020

So far in my Combine series I have mostly focussed on showing you how to use Combine using its built-in mechanisms. I've shown you how Combine's publishers and subscribers work, how you can use Combine for networking, to drive UI updates and how you can transform a Combine publisher's output. Knowing how to do all this with Combine is fantastic, but your knowledge is also still somewhat limited. For example, I haven't shown you at all how you can take an asynchronous operation in your existing code, and expose its result using Combine. Luckily, that is exactly what I'm going...

Read more...

Five ways to get better at receiving feedback

Published on: February 5, 2020

When I just started my career as a developer there was a lot I didn't know yet. There also were a lot of things I didn't understand or had never done before. I have always been lucky enough to work in places where I was able to learn and grow as needed, and most importantly, I was allowed to make mistakes. One of the hardest things wasn't that I was constantly learning and figuring out. That actually was the fun part! The hard bit was often receiving feedback. Whether it was feedback from clients, coworkers or teachers back in college....

Read more...

Using map, flatMap and compactMap in Combine

Published on: February 3, 2020

Oftentimes when you're working with Combine, you'll have publishers that produce a certain output. Sometimes this output is exactly what you need, but often the values that are output by a publisher need to be transformed or manipulated somehow before they are useful to their subscribers. The ability to do this is a huge part of what Combine is, what makes it so powerful, and Functional Reactive Programming (FRP) in general. In this week's post, I will show you several common operators that you can use to transform the output from your publishers and make them more useful. If you've...

Read more...

Updating UI with assign(to:on:) in Combine

Published on: January 29, 2020

So far in my series of posts about Combine, we have focussed on processing values and publishing them. In all of these posts, I used the sink method to subscribe to publishers and to handle their results. Today I would like to show you a different kind of built-in subscriber; assign(to:on:). This subscriber is perfect for subscribing to publishers and updating your UI in response to new values. In this post, I will show you how to use this subscriber, and I will show you how to avoid memory issues when using assign(to:on:). Using assign(to:on:) in your code If you've...

Read more...

Publishing property changes in Combine

Published on: January 27, 2020

In Combine, everything is considered a stream of values that are emitted over time. This means that sometimes a publisher can publish many values, and other times it publishes only a single value. And other times it errors and publishes no values at all. When your UI has to respond to changing data, or if you want to update your UI in response to a user's actions, you might consider the data and user input to both be streams of values. When we looked at networking in my previous post, it was possible to use a built-in publisher that is...

Read more...

Debugging network traffic with Charles

Published on: January 22, 2020

When you perform a URL Request in your app, you typically configure the request in your code and when it's all set up you pass it off to a URLSession data task, and the request should succeed if everything goes as expected. When the request is misconfigured, the server will hopefully return a useful error and you can fix your code accordingly. There are times, however, where the server does not give the information you need. Or your requests succeed but your results are not quite what you expect. It's times like these when I really wish that there was...

Read more...