问题
I'm writing a class to handle my server requests that return JSON to populate a TableView. This is my first time doing this sort of thing, and I was curious what is the be best paradigm to use here. Is something like delegation better than using dispatch_async? Pretty much Alamofire's response is asynchronous, so I can't return data out of it. Since my request is happening in a shared(it exists in a framework I created so I could use it in multiple targets) ServerManager class, I need to get it to the TableView some how, and I'm not sure what the best way to do that.
What are the pros of delegation over background threading and vice versa? I know this question probably gets asked a lot around here, but I couldn't seem to find a good explanation when I was searching.
回答1:
The method in ServerManager
should be passed a closure (block). This requires no delegation and no dispatches in the view controller.
class ServerManager {
func fetchObjectsWithOptions(options: [AnyObject], completion: (items: [AnyObject], error: ErrorType?) -> Void) {
// Use the options to setup and make the request
// Be sure it executes on the main thread
completion(items: items, error: nil)
// Any finishing needed
}
}
// ...
class MyTableViewController: UITableViewController {
lazy var serverManager = ServerManager()
var items: [AnyObject] = []
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
serverManager.fetchObjectsWithOptions([]) {
items, error in
if error == nil {
self.items = items
self.tableView.reloadData()
}
}
}
}
Closures are functions which can be assigned to a variables. Closures are relatively simple in Swift. Here is a closure that takes no parameters and has a void return type.
{ () -> Void in print("foo") }
Below, the variable x
has the type signature of () -> Void
, and is assigned the closure. Executing the closure is done just line calling a function, x()
.
let x: () -> Void = { () -> Void in print("foo") }
x() // prints foo
Closures can be passed around as function parameters. When funcWithClosure()
is called, it executes the closure.
func funcWithClosure(x: () -> Void) {
x()
}
funcWithClosure({ () -> Void in print("foo") })
Closures which take parameters have the parameters and their types specified as part of the closure type.
func funcWithClosure2(x: (string: String) -> Void) {
x(string: "foo") // <-- parameters must be named
}
funcWithClosure2({ (string: String) -> Void in print(string) })
The type inference engine allows you to remove the type from the closure.
funcWithClosure({ print("foo") }) // <-- No type declaration
funcWithClosure2({ string in print(string) }) // <-- Only parameter name
In addition, if a closure is the last parameter, you don't need the parentheses around the closure.
funcWithClosure { print("foo") }
Finally, here is an example with multiple parameter ending with a closure.
func funcWithString(string: String, closure: (string: String) -> Void) {
closure(string: string)
}
funcWithString("foo", closure: { (string: String) -> Void in print(string) })
Or, you can use the less verbose syntax.
funcWithString("foo") { string in print(string) }
来源:https://stackoverflow.com/questions/34548180/what-is-the-best-way-to-handle-response-from-alamofire-for-a-tableview-in-swift