Quick Tip

Find and copy Xcode device support files

Published on: April 1, 2020

Every once in a while I run into a situation where I update my iPhone to the latest iOS before I realize I'm still using an older version of Xcode for some projects. I usually realize this when Xcode tells me that it "Could not locate device support files". I'm sure many folks run into this problem. Luckily, we can fix this by copying the device support files from the new Xcode over to the old Xcode, or by grabbing the device support files from an external source. Copying device support files if you already have the latest Xcode installed...

Read more...

Calculating the difference in hours between two dates in Swift

Published on: March 25, 2020

Sometimes you need to calculate the difference between two dates in a specific format. For instance, you might need to know the difference between dates in hours. Or maybe you want to find out how many days there are between two dates. One approach for this would be to determine the number of seconds between two dates using timeIntervalSince: let differenceInSeconds = lhs.timeIntervalSince(rhs) You could use this difference in seconds to convert to hours, minutes or any other unit you might need. But we can do better in Swift using DateComponents. Given two dates, you can get the difference in...

Read more...

Removing duplicate values from an array in Swift

Published on: March 18, 2020

Arrays in Swift can hold on to all kinds of data. A common desire developers have when they use arrays, is to remove duplicate values from their arrays. Doing this is, unfortunately, not trivial. Objects that you store in an array are not guaranteed to be comparable. This means that it's not always possible to determine whether two objects are the same. For example, the following model is not comparable: struct Point { let x: Int let y: Int } However, a keen eye might notice that two instances of Point could easily be compared and two points that are...

Read more...

What is @escaping in Swift?

Published on: March 11, 2020

If you've ever written or used a function that accepts a closure as one of its arguments, it's likely that you've encountered the @escaping keyword. When a closure is marked as escaping in Swift, it means that the closure will outlive, or leave the scope that you've passed it to. Let's look at an example of a non-escaping closure: func doSomething(using closure: () -> Void) { closure() } The closure passed to doSomething(using:) is executed immediately within the doSomething(using:) function. Because the closure is executed immediately within the scope of doSomething(using:) we know that nothing that we do inside of...

Read more...

Reading and writing Property List files with Codable in Swift

Published on: March 4, 2020

You have probably seen and used a property list file at some point in your iOS journey. I know you have because every iOS app has an Info.plist file. It's possible to create and store your own .plist files to hold on to certain data, like user preferences that you don't want to store in UserDefaults for any reason at all. In this week's Quick Tip you will learn how you can read and write data from and to property list files using Swift's Codable protocol. Defining a model that can be stored in a property list Because Swift has...

Read more...

Using KeyPaths as functions in Swift 5.2

Published on: February 26, 2020

One of Swift 5.2's new features is the ability to use KeyPaths as functions. This can be extremely useful in cases where you'd only return the value of a certain KeyPath in a closure. Let's look at a pre-Swift 5.2 example where this is the case: // Swift 5.1 and earlier struct User { let id: UUID let name: String let age: Int } func extractUserIds(from users: [User]) -> [UUID] { return users.map { $0.id } } This code should look familiar to you. It's likely that you've written or seen something like this before. This code transforms an array...

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...

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...

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...

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...