Alamofire 学习笔记(一)

花了两天时间,把 Ray 关于 Alamofire 的文章 Part1Part2 看了一遍,代码也敲了,又去把 Alamofire 文档过了一遍,这周写一个 Demo,今天先来整理一下:)

基本使用方法

请求

import Alamofire

Alamofire.request(.GET, "http://httpbin.org/get")  

响应处理

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])  
         .response { request, response, data, error in
              println(request)
              println(response)
              println(error)
          }

Alamofire 从发出请求到收到响应,这一过程是异步的,但 response 回来的 completion block 是在主线程上的

响应序列化(内置的响应序列化方法)

  • response()
  • responseString(encoding: NSStringEncoding)
  • responseJSON(options: NSJSONReadingOptions)
  • responsePropertyList(options: NSPropertyListReadOptions)

可以链接起来使用:

Alamofire.request(.GET, "http://httpbin.org/get")  
         .responseString { _, _, string, _ in
             println(string)
         }
         .responseJSON { _, _, JSON, _ in
             println(JSON)
         }

HTTP Methods

Alamofire.Method 是一个枚举对象,列出了所有的操作,作为 request 的第一个参数使用

Alamofire.request(.POST, "http://httpbin.org/post")

Alamofire.request(.PUT, "http://httpbin.org/put")

Alamofire.request(.DELETE, "http://httpbin.org/delete")  

参数和参数编码

Get 操作

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])  
// http://httpbin.org/get?foo=bar

Post 操作

let parameters = [  
    "foo": "bar",
    "baz": ["a", 1],
    "qux": [
        "x": 1,
        "y": 2,
        "z": 3
    ]
]

Alamofire.request(.POST, "http://httpbin.org/post", parameters: parameters)  
// HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3

使用枚举对象 ParameterEncoding 可以将参数编码成 JSON,Property List,以及自定义格式:

enum ParameterEncoding {  
    case URL
    case JSON
    case PropertyList(format: NSPropertyListFormat, options: NSPropertyListWriteOptions)
    case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?))

    func encode(request: NSURLRequest, parameters: [String: AnyObject]?) -> (NSURLRequest, NSError?)
    { ... }
}

手动对 NSURLRequest 的参数编码:

let URL = NSURL(string: "http://httpbin.org/get")!  
var request = NSURLRequest(URL: URL)

let parameters = ["foo": "bar"]  
let encoding = Alamofire.ParameterEncoding.URL  
(request, _) = encoding.encode(request, parameters: parameters)

使用 JSON 对参数进行编码,进行一个 POST Request

let parameters = [  
    "foo": [1,2,3],
    "bar": [
        "baz": "qux"
    ]
]

Alamofire.request(.POST, "http://httpbin.org/post", parameters: parameters, encoding: .JSON)  
// HTTP body: {"foo": [1, 2, 3], "bar": {"baz": "qux"}}

HTTP Headers

添加 HTTP header 也很直接

let headers = [  
    "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
    "Content-Type": "application/x-www-form-urlencoded"
]

Alamofire.request(.GET, "http://httpbin.org/get", headers: headers)  
         .responseJSON { _, _, JSON, _ in
             println(JSON)
         }

上传数据

支持以下几种类型:

  • File
  • Data
  • Stream
  • MultipartFormData

上传文件,直接将文件的 NSURL 地址传给 upload 方法

let fileURL = NSBundle.mainBundle().URLForResource("Default", withExtension: "png")  
Alamofire.upload(.POST, "http://httpbin.org/post", file: fileURL)  

实时检测上传过程用 progress(closure:) 方法,(下载同样用该方法检测下载过程)定义如下:

public func progress(closure: ((Int64, Int64, Int64) -> Void)? = nil) -> Self  

该方法会在 上传/下载 的过程中反复被调用,第一个参数表示当前调用 读/写 的字节数,第二个参数表示目前为止已经 读/写 的字节总数,第三个参数表示整个文件的字节数

这里要特别注意,因为 progress(closure:) 是被反复调用的,所以里面的闭包 closure: 不会在主线程上执行,因此你在里面的任何关于 UI 的操作都要手动回主线程里

打印整个上传进度,Ray 是用 UIProgressView 来实时显示

Alamofire.upload(.POST, "http://httpbin.org/post", file: fileURL)  
         .progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
             println(totalBytesWritten)
         }
         .responseJSON { request, response, JSON, error in
             println(JSON)
         }

从多个 url 上传,然后组合在一起

Alamofire.upload(  
    .POST,
    URLString: "http://httpbin.org/post",
    multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
        multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
    },
    encodingCompletion: { encodingResult in
        switch encodingResult {
        case .Success(let upload, _, _):
            upload.responseJSON { request, response, JSON, error in
                println(JSON)
            }
        case .Failure(let encodingError):
            println(encodingError)
        }
    }
)

下载

  • 请求下载
  • 恢复下载

下载文件,完成后返回一个下载文件的 URL 地址,这里我们自己创建了一个,如果创建失败,系统会提供一个

Alamofire.download(.GET, "http://httpbin.org/stream/100") { temporaryURL, response in  
    let fileManager = NSFileManager.defaultManager()
    if let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
        let pathComponent = response.suggestedFilename
        return directoryURL.URLByAppendingPathComponent(pathComponent!)
    }

    return temporaryURL
}

Alamofire 也提供了默认的下载地址,其实也就是 DocumentDirectory

let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)  
Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destination)  

但这样如果服务器返回多个文件,重名的话会产生覆盖,可以在第一个 code 基础上加上 id 之类的进行区分

return directoryURL.URLByAppendingPathComponent("\(文件id)"+ "/" + pathComponent!)  

鉴权认证

支持四种形式的鉴权认证

  • HTTP 基本认证
  • HTTP 摘要认证
  • Kerberos 协议认证
  • NTLM windows 安全协议

HTTP 基本认证 authenticate 方法封装了用户名密码,供验证的时候使用

let user = "user"  
let password = "password"

Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")  
         .authenticate(user: user, password: password)
         .response { request, response, _, error in
             println(response)
         }

也可以用 Base64 进行加密后,放进 HTTP Header 中传输

let user = "user"  
let password = "password"

let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!  
let base64Credentials = credentialData.base64EncodedStringWithOptions(nil)

let headers = ["Authorization": "Basic \(base64Credentials)"]

Alamofire.request(.GET, "http://httpbin.org/basic-auth/user/password", headers: headers)  
         .responseJSON { _, _, JSON, _ in
             println(JSON)
         }

使用 NSURLCredential 来进行认证:

let user = "user"  
let password = "password"

let credential = NSURLCredential(user: user, password: password, persistence: .ForSession)

Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")  
         .authenticate(usingCredential: credential)
         .response { request, response, _, error in
             println(response)
         }

确认有效性

在对 response 进行处理之前,我们可以调用 validate 来进行验证

手动验证:

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])  
         .validate(statusCode: 200..<300)
         .validate(contentType: ["application/json"])
         .response { _, _, _, error in
             println(error)
         }

自动验证(statusCode 范围:200...299,Content-Type 和 header 中 Request 时的 Accept 相匹配)

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])  
         .validate()
         .response { _, _, _, error in
             println(error)
         }

-EOF-

如果感觉此文对你有帮助,请随意打赏支持作者 😘

chengway

认清生活真相之后依然热爱它!

Subscribe to Talk is cheap, Show me the world!

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!