Last active
April 8, 2017 04:44
-
-
Save keith-kurak/88914b0e1ced074ec584b4092190af4f to your computer and use it in GitHub Desktop.
Async List Builder Monstrosity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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