新人开始学习IOS开发,今天看了Alamofire的基本命令,参考了官网,总结一下,官方文档如下。可以用cocapods引入alamofire库:
https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md
AF.request("<url>").reponse { … }
此方法的完整定义:
open func request<Parameters: Encodable>(_ 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
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(...)
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。
例如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”
let encoder = URLEncodedFormParameterEncoder(encoder: URLEncodedFormEncoder(alphabetizeKeyValuePairs: false))
Format的传参根据需要进行编码的类型不同而不同,每一个参数对应的方法也不同,具体可以参考官方文档:
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#manual-authentication
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)
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)
}
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 Handler - Unserialized Response
func response(queue: DispatchQueue = .main,
completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self
// Response Serializer Handler - Serialize using the passed Serializer
func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
responseSerializer: Serializer,
completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void) -> Self
// Response Data Handler - Serialized into Data
func responseData(queue: DispatchQueue = .main,
dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods,
completionHandler: @escaping (AFDataResponse<Data>) -> Void) -> Self
// Response String Handler - Serialized into String
func responseString(queue: DispatchQueue = .main,
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
encoding: String.Encoding? = nil,
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods,
completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self
// Response Decodable Handler - Serialized into Decodable Type
func responseDecodable<T: Decodable>(of type: T.Type = T.self,
queue: DispatchQueue = .main,
dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<T>.defaultDataPreprocessor,
decoder: DataDecoder = JSONDecoder(),
emptyResponseCodes: Set<Int> = DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer<T>.defaultEmptyRequestMethods,
completionHandler: @escaping (AFDataResponse<T>) -> 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)
}
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)
}
}
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)
}
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)
}