The Days of Future Past

Syncing and Grouping Requests

Cory D. Wiles
2 min readJan 5, 2021

Pre iOS 13 if one wanted to run and sync a group of asynchronous requests they had their choice of the following:

While each of these techniques provide very powerful versitality, implementing thread-safe, edgecase / error proof code, in many instances, isn’t trivial. Most of the examples, tutorials and uses cases showing how to sync multiple asynchronous “operations” fell under the category of networking.

While it is true that grouping network requests is an extremely common task, a just as common, yet rarely discussed, task is the grouping of required requested system permissions, i.e. Microphone and SpeechRecognizer. For example, the SpokestackTray that I wrote, would be completely useless without having access to both the user’s microphone and speech recognition.

Combining It All Together

With iOS 13 came the new Combine framework. Within Combine comes our friend: Future

A publisher that eventually produces a single value and then finishes or fails.

Futures are great for handling asynchronous requests in a “synchronous” way without getting into queue management or callback hell. In my case, having heterogenous method signatures makes using Future the best approach for solving my problem.

I wrapped this into a simple class in case I needed to add more permissions.

Permissions.swift

let permission = Permission()
let _ = permission.hasGrantedPermissions
.sink(receiveCompletion: {completion in

switch completion {
case .finished:
print("finished in completion")
break
case .failure(let error):
print("error \(error) in completion")
break
}

}, receiveValue: {hasGranted in
print("hasGranted \(hasGranted)")
})

If you wanted to change the state of a class based upon the permission result then you could so something like

class ViewController: UIViewController {

var isReady = false {
didSet {
someHiddenView.isHidden = !isReady
}
}

override func viewDidLoad() {
super.viewDidLoad()
self.checkForPermissions()
}

func checkForPermissions() {

let permission = Permission()

let _ = permission.hasGrantedPermissions
.replaceError(with: false)
.assign(to: \.isReady, on: self)
}
}

--

--

Cory D. Wiles

I code stuff in Swift. I also raise children, workout, and make a perfect old fashioned.