Skip to content

Instantly share code, notes, and snippets.

@keith-kurak
Last active April 8, 2017 04:44
Show Gist options
  • Save keith-kurak/88914b0e1ced074ec584b4092190af4f to your computer and use it in GitHub Desktop.
Save keith-kurak/88914b0e1ced074ec584b4092190af4f to your computer and use it in GitHub Desktop.
Async List Builder Monstrosity
import Foundation
typealias ReturnCompletionBlock<T> = (T?) -> ()
//yes, this is a closure with a closure as a parameter
typealias AsyncListElementFunction<T> = (ReturnCompletionBlock<T>) -> ()
class AsyncListBuilder<T> {
var elementFunctions = [AsyncListElementFunction<T>]()
func add(elementFunction: @escaping AsyncListElementFunction<T>) {
self.elementFunctions.append(elementFunction)
}
func set(elementFunctions: [AsyncListElementFunction<T>]) {
self.elementFunctions = elementFunctions
}
func buildListFromElementFunctions(completionBlock: @escaping ([T]) -> ()) {
var elements = [T]()
let dispatchGroup = DispatchGroup()
//execute each function...
for function in self.elementFunctions {
dispatchGroup.enter()
//...passing in a completion block that leaves the dispatch group and adds the result to the list
function({(element) in
DispatchQueue.main.async {
if(element != nil) {
elements.append(element!)
}
dispatchGroup.leave()
}
})
}
dispatchGroup.notify(queue: DispatchQueue.main, execute: {
completionBlock(elements)
})
}
}
// -- HOW TO USE --
//for each key, generate a closure that will execute an async request for the Post
var elementFunctions = postKeys.map({(key) in
return {(outerCompletionBlock: @escaping (Post?) -> ()) in
ref.child("users").child(userId!).child("posts").child(postKey).observeSingleEvent(of: .value, with: {(postSnapshot)
//it's still awkward because you have to map each async call into another completion block and makes sure you call the completion block at the conclusion of the request
outerCompletionBlock(Post(fromSnapshot: postSnapshot)
})
}
})
let builder = AsyncListBuilder<Post>()
builder.set(elementFunctions: elementFunctions)
builder.buildListFromElementFunctions(completionBlock: {([Post] in
// use your list of Posts
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment