多个网站的多个 Alamofire 请求的正确模型

Posted

技术标签:

【中文标题】多个网站的多个 Alamofire 请求的正确模型【英文标题】:Proper model for multiple Alamofire requests for multiple websites 【发布时间】:2015-03-11 10:47:07 【问题描述】:

我正在使用 Alamofire 从网页中抓取一些数据,比如新闻。新闻是具有标题、内容、图片、日期、作者等内容的通用对象。但是对于每个网站,我使用不同的方法。对于一些我使用 json 对于其他我使用 hpple 来提取数据。如何为每个网站创建某种服务。我应该为每个网站创建不同的服务,还是有更好的方法为每个网站使用某种通用功能模板。喜欢

Login()
Fetch()
Populate()
return News(…..)

那么在我创建了新闻并填充了tableview之后,我该如何刷新News对象呢?由于 News 是通用的,它无法知道是谁用什么方法创建的。

【问题讨论】:

【参考方案1】:

有很多方法可以设计这种类型的抽象。如果可能的话,我倾向于在我的建筑设计中尽可能地倾向于简单。这里的一个很好的模式是使用带有类方法的 Service 对象来处理调用不同的服务、解析结果并调用成功或失败闭包。

您还可以使用完成处理程序,它不会将成功和失败分成两件事,但是您需要在调用者对象中处理我不太喜欢的失败或成功。下面是 Service 设计的示例。

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)
            
        
    

在视图控制器内部

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)")
        
    )

随意修改设计,但您喜欢根据您的用例对其进行定制。这种模式都不是一成不变的。它只是为您提供了一种构建不同服务的通用方法。 @mattt 在 Alamofire README 中也有一些非常酷的模式(路由器和 CRUD),我强烈建议您通读一遍。它们肯定更复杂,但仍需要 Service 类型的对象以最大限度地重用代码。

希望这有助于阐明一些问题。

【讨论】:

得到新闻后,如何从表格中刷新新闻内容?由于 news 是一个结构,它不知道是谁创建了它。所以它不能再次请求 FirstNewsService 获取新闻。我也很困惑 fetch() 如何等到登录功能结束。在登录完成工作之前不会立即触发 fetch 吗?在您之前的回答中,***.com/questions/28972847 您使用了完成块。我还尝试复制/粘贴该锅炉代码,但它给了我错误。由于您试图返回 4 个变量,但这些闭包不是无效且不允许参数吗? 对此我感到非常抱歉...我之前的回答非常离谱(恐怕早上太早代码太多了)。我已经编辑了正确处理异步行为的答案。 关于刷新内容,您在视图控制器中调用了该服务,以便您知道数据来自哪个服务。如果您需要确定还查询哪个服务以获取其他内容,那么您需要直接在 View Controller 中跟踪该状态,或者考虑使用另一个对象来跟踪此类信息。尽管它应该存在于服务中,但这似乎不像是逻辑类型。 首先感谢您编辑的答案。它肯定会有很大帮助。下面的事情是否可能。少说我有可能的 NewsType 的枚举,而在 News Struct 内部我有一个名为 var id:NewsType 的成员所以也许枚举可以将该功能作为属性?我不确定我该怎么做。我想要实现的是,我有一个包含可能新闻来源的表格,当我选择条目时,它将使用指定的获取器和一些主题来获取新闻。像 fetch(NewsType.CNN, "sports") 或 fetch(NewsType.BBC, "science") 这样每个人都将使用自己不同的 fetch 函数 绝对有可能。我建议将其作为一个单独的问题提出,因此我们不会劫持这个问题。另外,当您不在 cmets 中时,编写带有问题的示例代码块要容易得多。

以上是关于多个网站的多个 Alamofire 请求的正确模型的主要内容,如果未能解决你的问题,请参考以下文章

使用 Alamofire 和 SwiftyJSON 正确解析具有多个对象的 JSON 数组

Alamofire 多个请求

Alamofire 从多个请求中取消一个请求

如何使用操作查询发出多个 Alamofire 请求

我如何使用 Alamofire 取消多个请求?

使用多个 Alamofire 链接请求填充 tableview