Newcomers began to learn IOS development. Today, they read the basic commands of alamofire and referred to the official website. To sum up, the official documents are as follows. You can use cocapods to import the Alamo fire Library:
https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md
- Send request:
AF.request("<url>").reponse { ... }
Complete definition of this method:
open func request<Parameters: Encodable>(_ convertible: URLConvertible, method: HTTPMethod = .get, parameters: Parameters? = nil, encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default, headers: HTTPHeaders? = nil, interceptor: RequestInterceptor? = nil) -> DataRequest
The example in the first line actually uses this simple definition:
open func request(_urlRequest: URLRequestConvertible, interceptor: RequestInterceptor?=nil) ->DataRequest
- You can use the Modifier to customize the request
AF.request("https://httpbin.org/get", requestModifier: { $0.timeoutInterval = 5 }).response(...)
The request is written in the closure expression.
AF.request("https://httpbin.org/get") { urlRequest in urlRequest.timeoutInterval=5 urlRequest.allowsConstrainedNetworkAccess=false} .response(...)
- Add parameters to the request
The parameter must be of type encodeable and meet the ParameterEncoder protocol. The following example is an example of creating a Login request:
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) }
There are two types of encoders, one is JSON format JSONParameterEncoder, and the other is urlencodedformulalparameterencoder.
- Send request in URL encoded format
The API parameters for sending the request through the URL are different. The parameters include: (request path, request parameters (optional), request compiler (. methodDependent/.queryString/.httpBody)). The compiler determines according to the Http type of the request.
For example, POST request:
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
Starting from Swift4.x, the hash algorithm for the dictionary will cause internal sorting confusion when the Collection type is passed in. You can use URLEncodedFormEncoder to sort the key value pairs to be encoded.
let encoder = URLEncodedFormParameterEncoder(encoder: URLEncodedFormEncoder(alphabetizeKeyValuePairs: false))
The parameters of Format are encoded according to different types, and the corresponding methods of each parameter are also different. For details, please refer to the official document:
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#manual-authentication
- Send the request through JSON encoding
Sending requests through JSON doesn't seem to be as cumbersome as URL s. There are three types of encoders, all of which can know the meaning according to the name. Examples are as follows:
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"]}
You can customize the JSON encoder behavior through the wearing JSONEncoder instance:
let encoder = JSONEncoder() encoder.dateEncoding = .iso8601 encoder.keyEncodingStrategy = .convertToSnakeCase let parameterEncoder = JSONParameterEncoder(encoder: encoder)
You can also manually create parameters externally:
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:
There are two ways to create an HttpHeader:
One is similar to manually filling in key value pairs in the Header of POSTMAN:
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) }
The other is similar to filling in username and password in POSTMAN:
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 validation
Automatic verification (automatic verification will require the returned Http status code to be between 200-300):
AF.request("https://httpbin.org/get").validate().responseData { response in debugPrint(response) }
Manually verify and add an expression to the parameter:
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 processing
alamofire has five types of responders:
// 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 - does not do any processing, only returns according to the url:
AF.request("https://httpbin.org/get").response { response in debugPrint("Response: \(response)") }
2) Response Data Handler - extract the data of the response by serialization:
AF.request("https://httpbin.org/get").responseData { response in debugPrint("Response: \(response)") }
3) Response String Handler - String to retrieve the response by serialization:
AF.request("https://httpbin.org/get").responseString { response in debugPrint("Response: \(response)") }
4) Response Decodable Handler - converts Data to a DataDecoder by serialization (the type is defined by itself),
struct DecodableType: Decodable { let url: String } AF.request("https://httpbin.org/get").responseDecodable(of: DecodableType.self) { response in debugPrint("Response: \(response)") }
- authentication
Several ways of certification:
1) Available directly at 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) For the above variant, instantiate the URLCredential object:
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) Manual authentication, improve reuse and simplify code (there is no need to call the authenticate API, which is annoying):
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) }
- Download file
Alamo fire supports downloading to memory or hard disk. The downloaded files will be placed in a temporary folder and need to be transferred in time.
1) Basic examples:
AF.download("https://httpbin.org/image/png").responseURL { response in // Read file from provided file URL. }
2) Download to destination file:
As mentioned earlier, all file downloads will be placed in a temporary area, and a destination needs to be made. The destination is provided, and the closure operation will be performed before the file is moved to the destination. Two types can be specified:
. createIntermediateDirectories: if specified, creates an intermediate directory for the target URL.
. removePreviousFile: if specified, deletes the previous file from the destination 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) } }
More simply, you can directly use the API to complete the download operation:
let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory) AF.download("https://httpbin.org/image/png", to: destination)
3) Report download progress:
Using the downloadProgress API, you can report the download progress to the user.
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) Cancel and resume Download:
Canceling the download provides two API s:
Cancel (productingresumedata: bool): allows you to control whether to resume downloading. It can only be used on DownloadResponse
Cancel (byproducingresumedata: (resumedata: data?) - > void): the download can be resumed, but it can only be used in the completed program
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) } }
- Upload file
If there is only a small amount of data (such as sending a data object), it is sufficient to use request. But if you want to send pictures and so on, you can use upload ()
Here are three examples of uploading file s:
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) }
- Show upload progress
Like downloading, uploading can also show the progress of uploading. Use the 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) }