Combine

Comparing lifecycle management for async sequences and publishers

Published on: April 12, 2022

In my previous post you learned about some different use cases where you might have to choose between an async sequence and Combine while also clearly seeing that async sequence are almost always better looking in the examples I’ve used, it’s time to take a more realistic look at how you might be using each mechanism in your apps. The details on how the lifecycle of a Combine subscription or async for-loop should be handled will vary based on how you’re using them so I’ll be providing examples for two situations: Managing your lifecycles in SwiftUI Managing your lifecycles virtually...

Read more...

Comparing use cases for async sequences and publishers

Published on: April 12, 2022

Swift 5.5 introduces async/await and a whole new concurrency model that includes a new protocol: AsyncSequence. This protocol allows developers to asynchronously iterate over values coming from a sequence by awaiting them. This means that the sequence can generate or obtain its values asynchronously over time, and provide these values to a for-loop as they become available. If this sounds familiar, that’s because a Combine publisher does roughly the same thing. A publisher will obtain or generate its values (asynchronously) over time, and it will send these values to subscribers whenever they are available. While the basis of what we...

Read more...

Understanding Swift’s AsyncSequence

Published on: November 1, 2021

The biggest features in Swift 5.5 all revolve around its new and improved concurrency features. There's actors, async/await, and more. With these features folks are wondering whether async/await will replace Combine eventually. While I overall do not think that async/await can or will replace Combine on its own, Swift 5.5 comes with some concurrency features that provide very similar functionality to Combine. If you're curious about my thoughts on Combine and async/await specifically, I still believe that what I wrote about this topic earlier is true. Async/await will be a great tool for work that have a clearly defined start...

Read more...

What exactly is a Combine AnyCancellable?

Published on: August 24, 2021

If you've worked with Combine in your applications you'll know what it means when I tell you that you should always retain your cancellables. Cancellables are an important part of working with Combine, similar to how disposables are an important part of working with RxSwift. Interestingly, Swift Concurrency's AsyncSequence operates without an equivalent to cancellable (with memory leaks as a result). That said, in this post we'll only focus on Combine. For example, you might have built a publisher that wraps CLLocationManagerDelegate and exposes the user's current location with a currentLocation publisher that's a CurrentValueSubject<CLLocation, Never>. Subscribing to this publisher...

Read more...

Thoughts on Combine in an async/await world

Published on: June 8, 2021

When Apple announced their own Functional Reactive Programming framework at WWDC 2019 I was super excited. Finally, a simplified, easy to use framework that we could use to dip our toes in FRP. What made it even better is that SwiftUI makes heavy use of Combine, which means that Apple had to buy in to the technology themselves. This made it seem unlikely that Apple would abandon the technology any time soon. Then WWDC 2020 came around and there weren’t any meaningful changes to Combine. It was hardly even mentioned in the sessions. To me, this was a signal that...

Read more...

Observing the result of saving a background managed object context with Combine

Published on: December 7, 2020

I love posts where I get to put write about two of my favorite frameworks at the moment; Combine and Core Data. When you're working with Core Data, it's common to perform save operations asynchronously using a background context. You could even perform an asynchronous save on the main managed object context. Consider the following method that I added to an object that I wrote called StorageProvider: public extension StorageProvider { func addTask(name: String, description: String, nextDueDate: Date, frequency: Int, frequencyType: HouseHoldTask.FrequencyType) { persistentContainer.performBackgroundTask { context in let task = HouseHoldTask(context: context) task.name = name task.taskDescription = description task.nextDueDate =...

Read more...

Building a concurrency-proof token refresh flow in Combine

Published on: November 9, 2020

Refreshing access tokens is a common task for many apps that use OAuth or other authentication mechanisms. No matter what your authentication mechanism is, your tokens will expire (eventually) and you'll need to refresh them using a refresh token. Frameworks like RxSwift and Combine provide convenient ways to build pipelines that perform transformation after transformation on a succesful network response, allowing you to grab Data, manipulate and transform it to an instance of a model object or anything else. Programming the not-so-happy path where you need to refresh a token is not as simple. Especially because in an ideal world...

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

Observing changes to managed objects across contexts with Combine

Published on: October 12, 2020

A common pattern in Core Data is to fetch objects and show them in your UI using one managed object context, and then use another context to update, insert or delete managed objects. There are several ways for you to update your UI in response to these changes, for example by using an NSFetchedResultsController. I wrote about doing this in a SwiftUI app in an earlier post. In this week's post I will show you a useful technique that allows you to observe specific managed objects across different contexts so you can easily update your UI when, for example, that...

Read more...

Configuring error types when using flatMap in Combine

Published on: September 14, 2020

When you're using Combine for an app that has iOS 13 as its minimum deployment target, you have likely run into problems when you tried to apply a flatMap to certain publishers in Xcode 12. To be specific, you have probably seen the following error message: flatMap(maxPublishers:_:) is only available in iOS 14.0 or newer. When I first encountered this error I was somewhat stumped. Surely we had flatMap in iOS 13 too! If you've encountered this error and thought the same, let me reassure you. You're right. We had flatMap in iOS 13 too. We just gained new flavors...

Read more...