多个网站的多个 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 请求的正确模型的主要内容,如果未能解决你的问题,请参考以下文章