本章节由CocoaChina翻译组成员星夜暮晨(博客)翻译自raywenderlich:Intermediate Alamofire Tutorial,敬请勘误。
欢迎回到我们的 Alamofire 网络库使用教程,本文是此教程的第二部分,同时也是最后一个部分。
在教程的第一部分中,我们学习了 Alamofire 的一些基本用法,比如说发送 GET 请求、传递参数、创建请求路由以及创建自定义响应序列化方法。在学习的过程中,我们也生成了一个很赞的名为 Photomania 的图片库应用。在本教程的第二部分,您将会增加以下功能:
-
照片查看器
-
查看评论以及其他信息的功能
-
下载照片功能,附带有一个圆列进度条
-
优化网络访问以及图片缓存
-
下拉刷新操作
让我们开始吧
您可以使用您在教程第一部分所完成的项目来开始本章教程。但是如果您跳过了第一部分的教程或者对自己的项目没有信心的话,那么您也可以使用我们提供的标准项目。
提示:
如果您跳过了第一部分的教程,那么请不要忘记您首先应当从 500px.com 网站上获取消费者密钥,然后在Five100px.swift中用其替换必要的部分。关于如何获取该密钥,以及在何处使用它,都在本教程的第一部分:Alamofire 网络库基础教程中有详细说明。
生成并运行起始项目,以确定我们应用运行正常。图片预览功能能够正常工作,但是单击图片并不会将其以全屏打开。这就是我们所要解决的问题!
创建图片查看器
说句老实话,范型可以说是包括 Swift 在内的高级编程语言中最强大的特性之一。一般情况下,在我们这个项目中最好使用范型这个功能。
打开Five100px.swift,然后在文件顶部,即import Alamofire语句下方添加以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@objc public protocol ResponseObjectSerializable {
init(response: NSHTTPURLResponse, representation: AnyObject)
}
extension Alamofire.Request {
public func responseObject(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
let serializer: Serializer = { (request, response, data)
in
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
if
response != nil && JSON != nil {
return
(T(response: response!, representation: JSON!), nil)
}
else
{
return
(nil, serializationError)
}
}
return
response(serializer: serializer, completionHandler: { (request, response, object, error)
in
completionHandler(request, response, object as? T, error)
})
}
}
|
在上述的代码中,我们再一次给 Alamofire 创建了一个扩展,添加了新的响应序列化方法。这次,我们添加了.responseObject()函数。作为一个通用函数,它能够序列化所有符合ResponseObjectSerializable协议的数据对象。
这意味着,如果我们定义一个含有init(response:representation:)初始化方法的新类,那么 Alamofire 就能够自行从服务器返回该类型的对象。这时候,我们已经将序列化逻辑封装进了自定义类的内部。哈哈,是不是一个很赞的面向对象设计?
图片查看器使用的是PhotoInfo类,这个类遵守了ResponseObjectSerializable协议,并实现了所需的方法。不过您仍需要让这个类正式遵守ResponseObjectSerializable协议。
打开Five100px.swift,并且修改PhotoInfo类的声明来让其明确遵守ResponseObjectSerializable协议,如下所示:
1
|
class PhotoInfo: NSObject, ResponseObjectSerializable {
|
提示:
虽然毋需详细了解representation参数在PhotoInfo对象中是如何序列化的,但是感兴趣的读者可以去浏览required init(response:representation:)方法来了解其工作原理。
打开PhotoViewerViewController.swift,注意不是PhotoBrowserCollectionViewController.swift,然后在文件顶部加入一个必要的导入声明:
1
|
import Alamofire
|
接着,在viewDidLoad()方法内的底部加入以下代码:
1
|
loadPhoto()
|
您会得到一个找不到loadPhoto()的错误,但是不必担心,我们接下来就要实现这个函数。
仍然是在同一个文件当中,在setupView()方法前加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func loadPhoto() {
Alamofire.request(Five100px.Router.PhotoInfo(self.photoID, .Large)).validate().responseObject() {
(_, _, photoInfo: PhotoInfo?, error)
in
if
error == nil {
self.photoInfo = photoInfo
dispatch_async(dispatch_get_main_queue()) {
self.addButtomBar()
self.title = photoInfo!.name
}
|