What is the best way to handle response from Alamofire for a TableView in Swift using separate classes?

我的梦境 提交于 2019-12-08 12:46:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!