您的位置:首页 > 移动开发 > Swift

Alamofire 入门教程(下)

2016-07-19 10:48 316 查看

上篇地址

获取数据

在 ViewController 的 extension 里面,
uploadImage(_:progress:completion:)
的下面添加如下的代码:

func downloadTags(contentID: String, completion: ([String]) -> Void) {
Alamofire.request(
.GET,
"http://api.imagga.com/v1/tagging",
parameters: ["content": contentID],
headers: ["Authorization" : "Basic xxx"]
)
.responseJSON { response in
guard response.result.isSuccess else {
print("Error while fetching tags: \(response.result.error)")
completion([String]())
return
}

guard let responseJSON = response.result.value as? [String: AnyObject] else {
print("Invalid tag information received from service")
completion([String]())
return
}
print(responseJSON)
completion([String]())
}
}


同样把
Basic xxx
替换为你自己的 token,设置好 URL 以及对应的参数。

下一步,返回
uploadImage(_:progress:completion:)
替换
completion
中的代码:

self.downloadTags(firstFileID) { tags in
completion(tags: tags, colors: [PhotoColor]())
}


编译运行你的工程,上传一个文件,之后你在控制台就会看见返回的数据:



你不用关心
confidence
的分数,在本次教程中我们只使用
tag
的名称。

下一步,返回
downloadTags(_:completion:)
然后用下面的代码替换里面的
.responseJSON


// 1.
guard response.result.isSuccess else {
print("Error while fetching tags: \(response.result.error)")
completion([String]())
return
}

// 2.
guard let responseJSON = response.result.value as? [String: AnyObject],
results = responseJSON["results"] as? [AnyObject],
firstResult = results.first,
tagsAndConfidences = firstResult["tags"] as? [[String: AnyObject]] else {
print("Invalid tag information received from the service")
completion([String]())
return
}

// 3.
let tags = tagsAndConfidences.flatMap({ dict in
return dict["tag"] as? String
})

// 4.
completion(tags)


下面是每步的代码:

1. 检查响应是否成功;如果不成功,输出错误信息并调用 completion

2. 对返回 json 数据进行解析。

3. 迭代
tagsAndConfidences
数组,检索
tag
.

4. 调用
completion


注意:

你使用 Swift 的
flatMap
方法来进行迭代,这个方法在遇到值为
nil
的情况不会崩溃,并且会从返回结果中移除为
nil
的值。这可以让你使用条件解包(
as?
)来验证字典的值是否可以转换为一个字符串。

再一次编译运行你的工程,选择一涨图片,然后你会看到下面的界面:



在 ViewController extension
downloadTags(_:completion:)
下面添加如下代码:

func downloadColors(contentID: String, completion: ([PhotoColor]) -> Void) {
Alamofire.request(
.GET,
"http://api.imagga.com/v1/colors",
parameters: ["content": contentID, "extract_object_colors": NSNumber(int: 0)],
// 1.
headers: ["Authorization" : "Basic xxx"]
)
.responseJSON { response in
// 2.
guard response.result.isSuccess else {
print("Error while fetching colors: \(response.result.error)")
completion([PhotoColor]())
return
}

// 3.
guard let responseJSON = response.result.value as? [String: AnyObject],
results = responseJSON["results"] as? [AnyObject],
firstResult = results.first as? [String: AnyObject],
info = firstResult["info"] as? [String: AnyObject],
imageColors = info["image_colors"] as? [[String: AnyObject]] else {
print("Invalid color information received from service")
completion([PhotoColor]())
return
}

// 4.
let photoColors = imageColors.flatMap({ (dict) -> PhotoColor? in
guard let r = dict["r"] as? String,
g = dict["g"] as? String,
b = dict["b"] as? String,
closestPaletteColor = dict["closest_palette_color"] as? String else {
return nil
}
return PhotoColor(red: Int(r),
green: Int(g),
blue: Int(b),
colorName: closestPaletteColor)
})

// 5.
completion(photoColors)
}
}


最后,返回
uploadImage(_:progress:completion:)
方法,在
completion
里面的
success
的情况,添加下面的代码:

self.downloadTags(firstFileID) { tags in
self.downloadColors(firstFileID) { colors in
completion(tags: tags, colors: colors)
}
}


再一次编译运行你的工程,选择一涨图片,然后你会看到下面的界面:



优化 PhotoTagger

你可能已经注意到了,在
PhotoTagger
里面有重复代码。

Alamofire 提供了一个简单的方法来排除重复的代码并且提供集中配置。这就需要创建一个结构体,遵循
URLRequestConvertible
协议,并且更新你的上传和请求调用。

创建一个 Swift 文件,点击
File\New\File…
,然后在 iOS 下面选择 Swift 文件,点击下一步,文件命名为 ImaggaRouter.swift,然后点击创建。

在你新建的文件中添加下面的代码:

import Foundation
import Alamofire

public enum ImaggaRouter: URLRequestConvertible {
static let baseURLPath = "http://api.imagga.com/v1"
static let authenticationToken = "Basic xxx"

case Content
case Tags(String)
case Colors(String)

public var URLRequest: NSMutableURLRequest {
let result: (path: String, method: Alamofire.Method, parameters: [String: AnyObject]) = {
switch self {
case .Content:
return ("/content", .POST, [String: AnyObject]())
case .Tags(let contentID):
let params = [ "content" : contentID ]
return ("/tagging", .GET, params)
case .Colors(let contentID):
let params = [ "content" : contentID, "extract_object_colors" : NSNumber(int: 0) ]
return ("/colors", .GET, params)
}
}()

let URL = NSURL(string: ImaggaRouter.baseURLPath)!
let URLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(result.path))
URLRequest.HTTPMethod = result.method.rawValue
URLRequest.setValue(ImaggaRouter.authenticationToken, forHTTPHeaderField: "Authorization")
URLRequest.timeoutInterval = NSTimeInterval(10 * 1000)

let encoding = Alamofire.ParameterEncoding.URL

return encoding.encode(URLRequest, parameters: result.parameters).0
}
}


Basic xxx
替换为你自己的 token,设置好 URL 以及对应的参数。这个
router
会帮助我们创建
NSMutableURLRequest
实例,并且提公布了三种情况:
.Content
.Tags(String)
, 或
.Colors(String)
。现在所有的模板代码都在这里,如果你需要更新它的话。返回
uploadImage(_:progress:completion:)
方法,并且把
Alamofire.upload
替换成下面的代码:

Alamofire.upload(
ImaggaRouter.Content,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data: imageData, name: "imagefile",
fileName: "image.jpg", mimeType: "image/jpeg")
},
/// original code continues...


然后替换
downloadTags(_:completion:)
方法里的
Alamofire.request


Alamofire.request(ImaggaRouter.Tags(contentID))


最后,更新
downloadColors(_:completion:) with
代码里的
Alamofire.request


Alamofire.request(ImaggaRouter.Colors(contentID))


最后一次编译运行,所有的功能都像之前一样,也就意味着没有破坏你的 app,进行了代码重构。不错的工作!

最终工程代码

下载地址

不要忘记替换你自己的 token。

你也可以去 github 下载 Alamofire

原帖地址

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息