新人开始学习IOS开发,今天看了Alamofire的基本命令,参考了官网,总结一下,官方文档如下。可以用cocapods引入alamofire库:

https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md

发送请求:

AF.request("").reponse { … }

此方法的完整定义:

open func request(_ convertible: URLConvertible,

method: HTTPMethod = .get,

parameters: Parameters? = nil,

encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,

headers: HTTPHeaders? = nil,

interceptor: RequestInterceptor? = nil) -> DataRequest

第一行的例子其实使用的是这个简单的定义:

open func request(_urlRequest: URLRequestConvertible,

interceptor: RequestInterceptor?=nil) ->DataRequest

可以使用Modifier来自定义请求

AF.request("https://httpbin.org/get", requestModifier: { $0.timeoutInterval = 5 }).response(...)

请求就写在闭包表达式里面。

AF.request("https://httpbin.org/get") { urlRequest in

urlRequest.timeoutInterval=5

urlRequest.allowsConstrainedNetworkAccess=false}

.response(...)

往请求里面添加参数 参数必须是Encodable类型,并且满足ParameterEncoder协议。如下例子就是创建一个Login请求的例子:

struct Login: Encodable {

let email: String

let password: String

}

let login = Login(email: "test@test.test", password: "testPassword")

AF.request("https://httpbin.org/post",

method: .post,

parameters: login,

encoder: JSONParameterEncoder.default).response { response in

debugPrint(response)

}

encoder有两种,一种是JSON格式的JSONParameterEncoder,另一种是URLEncodedFormParameterEncoder。

通过URL编码格式发送请求 通过URL发送请求的API参数不同,参数有:(请求路径、请求参数(可选)、请求编译器(.methodDependent/.queryString/.httpBody)),编译器根据请求的Http类型决定。

例如POST请求: let parameters: [String: [String]] = [ “foo”: [“bar”], “baz”: [“a”, “b”], “qux”: [“x”, “y”, “z”] ]

// All three of these calls are equivalent

AF.request("https://httpbin.org/post", method: .post, parameters: parameters)

AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder.default)

AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder(destination: .httpBody))

// HTTP body: “qux[]=x&qux[]=y&qux[]=z&baz[]=a&baz[]=b&foo[]=bar”

URLEncodedFormEncoder 从Swift4.x开始,对字典采用哈希算法会导致在传入Collection类型的时候内部排序混乱,可以使用URLEncodedFormEncoder来对需要编码的键值对进行排序。

let encoder = URLEncodedFormParameterEncoder(encoder: URLEncodedFormEncoder(alphabetizeKeyValuePairs: false))

Format的传参根据需要进行编码的类型不同而不同,每一个参数对应的方法也不同,具体可以参考官方文档: https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#manual-authentication

通过JSON编码发送请求 通过JSON发送请求似乎就没有URL那么麻烦了。编码器的种类有3种,都是可以根据名字知道意思的。例子如下:

let parameters: [String: [String]] = [

"foo": ["bar"],

"baz": ["a", "b"],

"qux": ["x", "y", "z"]

]

AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: JSONParameterEncoder.default)

AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: JSONParameterEncoder.prettyPrinted)

AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: JSONParameterEncoder.sortedKeys)

// HTTP body: {"baz":["a","b"],"foo":["bar"],"qux":["x","y","z"]}

可以自定义JSON编码器行为,通过穿件JSONEncoder实例来实现:

let encoder = JSONEncoder()

encoder.dateEncoding = .iso8601

encoder.keyEncodingStrategy = .convertToSnakeCase

let parameterEncoder = JSONParameterEncoder(encoder: encoder)

也可以在外部手动创建参数:

let url = URL(string: "https://httpbin.org/get")!

var urlRequest = URLRequest(url: url)

let parameters = ["foo": "bar"]

let encodedURLRequest = try URLEncodedFormParameterEncoder.default.encode(parameters,

into: urlRequest)

HttpHeader: 创建HttpHeader的方式有两种: 一种是类似于在POSTMAN的Header中手动填写键值对的方式:

let headers: HTTPHeaders = [

"Authorization": "Basic VXNlcm5hbWU6UGFzc3dvcmQ=",

"Accept": "application/json"

]

AF.request("https://httpbin.org/headers", headers: headers).responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

另一种是类似于POSTMAN中填写username和password的方式:

let headers: HTTPHeaders = [

.authorization(username: "Username", password: "Password"),

.accept("application/json")

]

AF.request("https://httpbin.org/headers", headers: headers).responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

Response验证 自动化验证(自动化验证会要求返回的Http状态码在200-300之间):

AF.request("https://httpbin.org/get").validate().responseData { response in

debugPrint(response)

}

手动验证,在传参中添加表达式:

AF.request("https://httpbin.org/get")

.validate(statusCode: 200..<300)

.validate(contentType: ["application/json"])

.responseData { response in

switch response.result {

case .success:

print("Validation Successful")

case let .failure(error):

print(error)

}

}

Response处理 alamofire有5种响应体:

// Response Handler - Unserialized Response

func response(queue: DispatchQueue = .main,

completionHandler: @escaping (AFDataResponse) -> Void) -> Self

// Response Serializer Handler - Serialize using the passed Serializer

func response(queue: DispatchQueue = .main,

responseSerializer: Serializer,

completionHandler: @escaping (AFDataResponse) -> Void) -> Self

// Response Data Handler - Serialized into Data

func responseData(queue: DispatchQueue = .main,

dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,

emptyResponseCodes: Set = DataResponseSerializer.defaultEmptyResponseCodes,

emptyRequestMethods: Set = DataResponseSerializer.defaultEmptyRequestMethods,

completionHandler: @escaping (AFDataResponse) -> Void) -> Self

// Response String Handler - Serialized into String

func responseString(queue: DispatchQueue = .main,

dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,

encoding: String.Encoding? = nil,

emptyResponseCodes: Set = StringResponseSerializer.defaultEmptyResponseCodes,

emptyRequestMethods: Set = StringResponseSerializer.defaultEmptyRequestMethods,

completionHandler: @escaping (AFDataResponse) -> Void) -> Self

// Response Decodable Handler - Serialized into Decodable Type

func responseDecodable(of type: T.Type = T.self,

queue: DispatchQueue = .main,

dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,

decoder: DataDecoder = JSONDecoder(),

emptyResponseCodes: Set = DecodableResponseSerializer.defaultEmptyResponseCodes,

emptyRequestMethods: Set = DecodableResponseSerializer.defaultEmptyRequestMethods,

completionHandler: @escaping (AFDataResponse) -> Void) -> Self

1)Response Handler - 不做任何处理,仅仅根据url进行返回:

AF.request("https://httpbin.org/get").response { response in

debugPrint("Response: \(response)")

}

2)Response Data Handler - 通过序列化提取出响应的数据:

AF.request("https://httpbin.org/get").responseData { response in

debugPrint("Response: \(response)")

}

3)Response String Handler - 通过序列化提取出响应的String:

AF.request("https://httpbin.org/get").responseString { response in

debugPrint("Response: \(response)")

}

4)Response Decodable Handler - 通过序列化将Data转换为DataDecoder(类型自己定义),

struct DecodableType: Decodable { let url: String }

AF.request("https://httpbin.org/get").responseDecodable(of: DecodableType.self) { response in

debugPrint("Response: \(response)")

}

认证 认证的几种方式:

1)直接在url种提供:

let user = "user"

let password = "password"

AF.request("https://httpbin.org/basic-auth/\(user)/\(password)")

.authenticate(username: user, password: password)

.responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

2)上面的变体,实例化URLCredential对象:

let user = "user"

let password = "password"

let credential = URLCredential(user: user, password: password, persistence: .forSession)

AF.request("https://httpbin.org/basic-auth/\(user)/\(password)")

.authenticate(with: credential)

.responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

3)手动认证,提高复用,简化代码(不用调用authenticate这个API,看着烦):

let user = "user"

let password = "password"

let headers: HTTPHeaders = [.authorization(username: user, password: password)]

AF.request("https://httpbin.org/basic-auth/user/password", headers: headers)

.responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

下载file alamofire支持下载到内存或者硬盘上,下载的文件都会放在一个临时文件夹里,需要及时转移。

1)基本例子:

AF.download("https://httpbin.org/image/png").responseURL { response in

// Read file from provided file URL.

}

2)下载到目的地文件: 正如前面所说的,所有的文件下载都会放在一个临时区,需要制定destination。提供Destination,会在文件移动到destination之前执行其中的闭包操作,可以指定两种: .createIntermediateDirectories:如果指定,则为目标 URL 创建中间目录。 .removePreviousFile: 如果指定,则从目标 URL 中删除上一个文件。

let destination: DownloadRequest.Destination = { _, _ in

let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

let fileURL = documentsURL.appendingPathComponent("image.png")

return (fileURL, [.removePreviousFile, .createIntermediateDirectories])

}

AF.download("https://httpbin.org/image/png", to: destination).response { response in

debugPrint(response)

if response.error == nil, let imagePath = response.fileURL?.path {

let image = UIImage(contentsOfFile: imagePath)

}

}

更简单的,直接使用API完成下载操作:

let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)

AF.download("https://httpbin.org/image/png", to: destination)

3)报告下载进度: 使用downloadProgress API可以向用户报告下载进度。

AF.download("https://httpbin.org/image/png")

.downloadProgress { progress in

print("Download Progress: \(progress.fractionCompleted)")

}

.responseData { response in

if let data = response.value {

let image = UIImage(data: data)

}

}

4)取消和恢复下载: 取消下载提供了两个API: cancel(producingResumeData: Bool):允许控制是否恢复下载,只能在DownloadResponse上用 cancel(byProducingResumeData: (_ resumeData: Data?) -> Void):允许恢复下载,但是只能在完成程序中使用

var resumeData: Data!

let download = AF.download("https://httpbin.org/image/png").responseData { response in

if let data = response.value {

let image = UIImage(data: data)

}

}

// download.cancel(producingResumeData: true) // Makes resumeData available in response only.

download.cancel { data in

resumeData = data

}

AF.download(resumingWith: resumeData).responseData { response in

if let data = response.value {

let image = UIImage(data: data)

}

}

上传file 如果只是少量的数据(比如发送一个数据对象),用request就足够了。但是如果要发送图片之类的,可以使用upload() 下面是三个上传file的例子: 1)

let data = Data("data".utf8)

AF.upload(data, to: "https://httpbin.org/post").responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

2)

let fileURL = Bundle.main.url(forResource: "video", withExtension: "mov")

AF.upload(fileURL, to: "https://httpbin.org/post").responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

3)

AF.upload(multipartFormData: { multipartFormData in

multipartFormData.append(Data("one".utf8), withName: "one")

multipartFormData.append(Data("two".utf8), withName: "two")

}, to: "https://httpbin.org/post")

.responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

展示上传进度 和下载一样,上传也可以展示上传的进度,使用uploadProgress API:

let fileURL = Bundle.main.url(forResource: "video", withExtension: "mov")

AF.upload(fileURL, to: "https://httpbin.org/post")

.uploadProgress { progress in

print("Upload Progress: \(progress.fractionCompleted)")

}

.downloadProgress { progress in

print("Download Progress: \(progress.fractionCompleted)")

}

.responseDecodable(of: DecodableType.self) { response in

debugPrint(response)

}

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。