Proper model for multiple Alamofire requests for multiple websites

♀尐吖头ヾ 提交于 2019-12-03 05:11:52

There are many ways to design this type of abstraction. I tend to lean towards simplicity as much as possible in my architectural designs if possible. A great pattern here is to use a Service object with class methods to handle calling your different services, parsing the result and calling a success or failure closure.

You can also use a completion handler that doesn't split the success and failure into two things, but then you need to handle the failure or success in your caller objects which I don't really like. Here's an example of the Service design in action.

FirstNewsService

import Alamofire

struct News {
    let title: String
    let content: String
    let date: NSDate
    let author: String
}

class FirstNewsService {

    typealias NewsSuccessHandler = ([News]) -> Void
    typealias NewsFailureHandler = (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void

    // MARK: - Fetching News Methods

    class func getNews(#success: NewsSuccessHandler, failure: NewsFailureHandler) {
        login(
            success: { apiKey in
                FirstNewsService.fetch(
                    apiKey: apiKey,
                    success: { news in
                        success(news)
                    },
                    failure: { response, json, error in
                        failure(response, json, error)
                    }
                )
            },
            failure: { response, json, error in
                failure(response, json, error)
            }
        )
    }

    // MARK: - Private - Helper Methods

    private class func login(#success: (String) -> Void, failure: (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) {
        let request = Alamofire.request(.GET, "login/url")
        request.responseJSON { _, response, json, error in
            if let error = error {
                failure(response, json, error)
            } else {
                // NOTE: You'll need to parse here...I would suggest using SwiftyJSON
                let apiKey = "12345678"
                success(apiKey)
            }
        }
    }

    private class func fetch(
        #apiKey: String,
        success: ([News]) -> Void,
        failure: (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void)
    {
        let request = Alamofire.request(.GET, "fetch/url")
        request.responseJSON { _, _, json, error in
            if let error = error {
                failure(response, json, error)
            } else {
                // NOTE: You'll need to parse here...I would suggest using SwiftyJSON
                let news = [News]()
                success(news)
            }
        }
    }
}

Inside a View Controller

override func viewDidLoad() {
    super.viewDidLoad()

    FirstNewsService.getNews(
        success: { news in
            // Do something awesome with that news
            self.tableView.reloadData()
        },
        failure: { response, json, error in
            // Be flexible here...do you want to retry, pull to refresh, does it matter what the response status code was?
            println("Response: \(response)")
            println("Error: \(error)")
        }
    )
}

Feel free to mod the design however you like to tailor it to your use cases. None of this pattern is set in stone. It just gives you a common way to construct different services. @mattt also has some really cool patterns (Router and CRUD) in the Alamofire README which I would highly recommend reading through. They are definitely more complicated though and still require a Service type of object to maximize code reuse.

Hopefully that helps shed some light.

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