1 min read


Last Updated - Platform 23.0 - SDK 18.0

The PoqSDK ensures that some core mechanism are thread-safe and provides a new API for asynchronous work based on the Swift Task API.

Concurrent Mechanisms

With v23.0 the SDK aims to ensure that some core and commonly used mechanisms are thread-safe. This avoids concurrency crashes that can be hard to track down.

It is completely possible to break this by replacing the default implementations with custom implementations. Sub-classing is preferred as these mechanisms should still provide concurrency.


Containers are concurrent using an internal recursive lock.


Accessing the current app config via AppConfig.current or AppConfigRepository has concurrency built into the repository. For advanced implementations it is better to subclass the PoqAppConfigService rather than the repository.


Accessing or modifying the user via User.current or UserRepository has concurrency and in-memory persistence built into the repository. The PoqUserRepository is open to sub-classing but only provides a small set of customisable functions.


The default NetworkSession and Authenticator implementations are concurrent.

Feature services use the task API which uses async / await under the hood. It is important to note that asnyc / await is not guaranteed to be concurrent but leads to better / robust concurrent code.


The AsyncTask API was introduced in v23.0 to replace all concurrent closure and delegate based operations and functions. With the initial release they replace all PoqSDK service functions to return NetworkTask types.

Unlike Swift Tasks, tasks do not execute immediately. Instead they evaluate when you execute them later. Tasks provide chainable SwiftUI style syntax similar to Combine publishers but can be executed in many ways:

  • Using async / await via await task.execute()
  • Using closures via task.execute { result in }
  • Using Combine via task.executePublisher()

This provides a solid foundation for future methods that are introduced to Swift and allows us to phase their roll out across the SDK continuing with closures.

Network tasks are an special typealias with additional convenience functions (read more here). But all tasks have convenience function for mapping or chaining tasks:

  • Use task.map to map the successful output of a previous task.
  • Use task.catch to catch and map errors from the previous task.
  • Use task.then or thenOnMain to perform an addition task after the previous completes.

This API will eventually be rolled out to repositories with the hope to providing asynchronous middleware.