Equivalent of Request.serializeResponseJSON - Migration Alamofire 5 - swift

I have a problem with the following code:
func request(url: URL, completionHandler: #escaping (AFDataResponse<Any>) -> Void) {
let httpResponse = fakeResponse.response
let data = fakeResponse.data
let error = fakeResponse.error
let result = Request.serializeResponseJSON(options: .allowFragments, response: httpResponse, data: data, error: error)
guard let url = urlBuild(queryType: "q", from: "0", to: "10", uri: nil) else { return }
let urlRequest = URLRequest(url: url)
completionHandler(AFDataResponse(request: urlRequest, response: httpResponse, data: data, result: result))
}
I get the following error with Alamofire 5: Type 'Request' has no member 'serializeResponseJSON'.
I'm new to development with Swift and Alamofire, and I can't find a method equivalent to Request.serializeResponseJSON in Alamofire 5.
Thanks in advance for your help :)

All of the serialize methods from previous versions of Alamofire have been refactored into concrete types. For example, serializeResponseJSON has been replaced by the JSONResponseSerializer, which you can use with the response(responseSerializer:) method. However, for your usage, you shouldn't need to create an instance directly, as you can pass the same parameters to responseJSON. I suggest you use responseDecodable with Decodable types instead of responseJSON, as it will ensure your types are properly parsed.
I also suggest you read through our Usage, Advanced Usage, and API documentation and find some newer tutorials as you start using Alamofire.

Related

ParameterEncoder Problem Updating Alamofire from version 4 to 5

I am updating my project from Alamofire version 4 to 5. And I am running into a snag. I use to encode my parameters with the follow :
// This struct lets us keep the square brackets in the HTTP GET Request vars to keep the php arrays in tact for the backend
struct BracketGetEncoding: ParameterEncoding {
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var request = try URLEncoding().encode(urlRequest, with: parameters)
request.url = URL(string: request.url!.absoluteString.replacingOccurrences(of: "%5B", with: "[").replacingOccurrences(of: "%5D", with: "]"))
return request
}
}
let request = AF.request(urlString, method: method, parameters: parameters, encoder: BracketGetEncoding(), headers: getRequestHeadersAsHTTPHeaders(), interceptor: nil, requestModifier: nil)
But I am trying to find the equivilant with the update. It now takes a ParameterEncoder instead of a ParameterEncoding.
There are two top level request methods: one that takes the new ParameterEncoder type, and one that takes the older ParameterEncoding type. You can use the old one by changing your encoder parameter to encoding.
I suggest you transition to the ParameterEncoder version when you can, as we're not sure if ParameterEncoding will be supported in the next major version of Alamofire.
Here is the update for people who are looking to do the same thing :
// This struct lets us keep the square brackets in the HTTP GET Request vars to keep the php arrays in tact for the backend
struct BracketParameterEncoder : ParameterEncoder {
func encode<Parameters>(_ parameters: Parameters?, into urlRequest: URLRequest) throws -> URLRequest where Parameters : Encodable {
var request = try URLEncodedFormParameterEncoder.default.encode(parameters, into: urlRequest)
request.url = URL(string: request.url!.absoluteString.replacingOccurrences(of: "%5B", with: "[").replacingOccurrences(of: "%5D", with: "]"))
return request
}
}

How to get original requests in Alamofire 5?

I made a wrapper for Alamofire which makes the data request first and then it prints the details of original URLRequest.
let dataRequest = session.request(url, method: .get, parameters: parameters)
let originalRequest = dataRequest.request
// Now print somehow the details of original request.
It worked fine on Alamofire 4.9, but it stopped in the newest 5.0 version. The problem is that dataRequest.request is nil. Why this behavior has changed? How can I access URLRequest underneath DataRequest?
URLRequests are now created asynchronously in Alamofire 5, so you're not going to be able to access the value immediately. Depending on what you're doing with the URLRequest there may be other solutions. For logging we recommend using the new EventMonitor protocol. You can read our documentation to see more, but adding a simple logger is straightforward:
final class Logger: EventMonitor {
let queue = DispatchQueue(label: ...)
// Event called when any type of Request is resumed.
func requestDidResume(_ request: Request) {
print("Resuming: \(request)")
}
// Event called whenever a DataRequest has parsed a response.
func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
debugPrint("Finished: \(response)")
}
}
let logger = Logger()
let session = Session(eventMonitors: [logger])
I had to obtain the URLRequest in a test case. Solved it by adding .responseData and using XCTestExpectation to wait for the async code to return:
func testThatHeadersContainContentEncoding() {
let exp = expectation(description: "\(#function)\(#line)")
let request = AF.request("http://test.org",
method: .post, parameters: ["test":"parameter"],
encoding: GZIPEncoding.default,
headers: ["Other":"Header"])
request.responseData { data in
let myHeader = request.request?.value(forHTTPHeaderField: additionalHeader.dictionary.keys.first!)
// .. do my tests
exp.fulfill()
}
waitForExpectations(timeout: 10, handler: nil)
}

Correct way to retrieve json data from remote url using swift 4 for an array

I am trying to see what is the latest and greatest way to retrieve json data in swift 4 (using Codable structure).
I have the following json data in a remote url:
[
{
"products": [
{
"productid": "01",
"price": "01"
},
{
"productid": "02",
"price": "02"
}
]
}
]
I have also setup the corresponding codable structure. My questions is what would be the correct way to retrieve this data using the latest techniques for swift 4.
I am seeing various ways such as:
DataManager.getJSONFromURL ...
let jsonData = try Data(contentsOf: URL ...
let task = URLSession.shared.dataTask(with: url) ...
try JSONSerialization.data...
I would like to know which is the correct (latest) format for retrieving json data using swift 4 from a remote URL. Thank you.
I found the answer to my question.
Apple announced Swift 4 as part of Xcode 9 at WWDC 2017. It brings some really nice improvements to existing Swift 3 features as well as stability. The latest ways of working with REST API in Swift 4 is using URLSession and JSONDecoder. The later was introduced with Swift 4.
In Swift 3, most of developers used third party frameworks such as SwiftyJson and Alamofire in order to work with REST APIs. The reason for this, most of the time, was that parsing JSON using Swift was very tedious. More precisely - you had to set up initializer in your Model, had to do loops to assign values in your controller, had to typecast values and so on. You could always copy/paste your code, but still it was overwhelming. With Swift 4 all you will need to do is to write just a single line to decode and parse JSON.
URLSession and JSONDecoder are all you need in Swift 4 for retrieving json data from a remote url.
For more information and an example, you can check this site:
URLSession and JSONDecoder in Swift 4
func getRequestWithUrl(url : String ,onCompletionHandler : #escaping ([String : Any]?) -> Void){
let headers : HTTPHeaders = [
"X-Api-Key": "EPE67704498C76B16CF29B956B2A2E91",
"Accept": "application/json",
]
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
switch response.result {
case .success:
onCompletionHandler(response.result.value as? [String : Any])
break
case .failure(_):
onCompletionHandler(nil)
}
}
}
we have an API which allows us to create a new board with a title “New
York Highlights”. For this, using Alamofire the code is very easy:
AF.request("https://api.mywebserver.com/v1/board", method: .get, parameters: ["title": "New York Highlights"])
.validate(statusCode: 200..<300)
.responseDecodable { (response: DataResponse) in
switch response.result {
case .success(let board):
print("Created board title is \(board.title)") // New York Highlights
case .failure(let error):
print("Board creation failed with error: \(error.localizedDescription)")
}
}
For Alamofire you need to install framework for more detail read this document
Doing exactly the same with the URLSession API requires a bit more of
work.
enum Error: Swift.Error {
case requestFailed
}
// Build up the URL
var components = URLComponents(string: "https://api.mywebserver.com/v1/board")!
components.queryItems = ["title": "New York Highlights"].map { (key, value) in
URLQueryItem(name: key, value: value)
}
// Generate and execute the request
let request = try! URLRequest(url: components.url!, method: .get)
URLSession.shared.dataTask(with: request) { (data, response, error) in
do {
guard let data = data,
let response = response as? HTTPURLResponse, (200 ..< 300) ~= response.statusCode,
error == nil else {
// Data was nil, validation failed or an error occurred.
throw error ?? Error.requestFailed
}
let board = try JSONDecoder().decode(Board.self, from: data)
print("Created board title is \(board.title)") // New York Highlights
} catch {
print("Board creation failed with error: \(error.localizedDescription)")
}
}
credit

Cannot do Alamofire request in Swift 4

I get this error and I have no idea why I get it. It is not shown in the picture but I do import UIKit and Alamofire. It would be great if you could let me know what the problem is.
I think the main problem is in the Alamofire.request(.GET, currentWeatherURL) part.
func downloadWeatherDetails(completed: DownloadComplete) {
//Alamofire Download
let currentWeatherURL = URL(string: CURRENT_WEATHER_URL)!
Alamofire.request(.GET, currentWeatherURL).responseJSON { response in
let result = response.result
print(result)
}
}
There are several issues with your code:
The order of your parameters is wrong, the request URL should prepend the method type, which should have the name method.
Method types are now lowercased in Alamofire.
You should not force unwrap the URL initializer - moreover, Alamofire does this for you automatically, just pass the string as a parameter.
Here is your code, fixed:
func downloadWeatherDetails(completed: DownloadComplete) {
Alamofire.request(CURRENT_WEATHER_URL, method: .get).responseJSON { response in
let result = response.result
print(result)
}
}

HTTP Request error using Alamofire

I am trying to access my MAMP database webservice using Alamofire. Following is my code:
Following is my router to construct my URL:
enum Router: URLRequestConvertible {
static let baseURLString = "http://pushchat.local:44447/"
case PostJoinRequest(String,String,String,String,String)
var URLRequest: NSURLRequest {
let (path: String, parameters: [String: AnyObject]) = {
switch self {
case .PostJoinRequest (let addPath, let userID, let token, let nickName, let secretCode):
let params = ["cmd": "join", "user_id": "\(userID)", "token": "\(token)", "name": "\(nickName)", "code": "\(secretCode)"]
return (addPath, params)
}
}()
let URL = NSURL(string: Router.baseURLString)
let URLRequest = NSURLRequest(URL: URL!.URLByAppendingPathComponent(path))
let encoding = Alamofire.ParameterEncoding.URL
return encoding.encode(URLRequest, parameters: parameters).0
}
}
Following is my viewdidload code:
Alamofire.request(.POST,Router.PostJoinRequest("api.php","12345678901234","12345678901234","ABCDEF","TopSecret")).responseJSON()
{(request, response, JSON, error) in
println(JSON)
}
Following is the compile error:
Cannot invoke 'responseJSON' with an argument list of type '((,,,)->_)'
Following is the declaration from Almofire for your reference.
:param: method The HTTP method.
:param: URLString The URL string.
:param: parameters The parameters. `nil` by default.
:param: encoding The parameter encoding. `.URL` by default.
:returns: The created request.
*/
// public func request(method: Method, _ URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL) -> Request {
// return request(encoding.encode(URLRequest(method, URLString), parameters: parameters).0)
// }
Please let me know why am I facing this issue while chaining and what is it that I am not doing right?
Thanks for your help.
Dev
The compiler error message is really misleading – there is no problem with responseJSON but with request method itself.
In fact compiler does not like your second parameter. You are passing URLRequestConvertible but URLStringConvertible is expected (see the signature you posted).
Maybe you wanted to call another version of request method:
//:param: URLRequest The URL request
//:returns: The created request.
public func request(URLRequest: URLRequestConvertible) -> Request
In that case you have to adjust your Router class and set HTTP method into NSURLRequest created inside. For example:
let URLRequest = NSMutableURLRequest(URL: URL!.URLByAppendingPathComponent(path))
URLRequest.HTTPMethod = "POST"
Note you will also probably need to use another parameter/data encoding.