Migration Alamofire 4 to 5 build issue - ios

I am doing migration after 2 years a lots things have been changed, now flagging a lots of error while building. Most are related to Alamofire 5. Now there are many error keeps coming fixing one by one.
Error: // ERROR: Cannot specialize non-generic type
public static func ObjMappingSerializer<T: Mappable>(_ keyPath: String?) -> DataResponseSerializer<T> { 'DataResponseSerializer'
return DataResponseSerializer { request, response, data, error in
//LogResponse(response, data: data, error: error)
Logger._reqresLogger.logResponse(response, data: data, error: error)
guard error == nil else {
return .failure(parseErrorResponse(data: data, response: response, errorType: error!))
}
guard let _ = data else {
return .failure(errorForNilData())
}
let JSONToMap = deserializeJSON(request: request, response: response, data: data, error: error, keyPath: keyPath)
if let json = JSONToMap as? [String:Any], let parsedObject = Mapper<T>().map(JSON:json) {
return .success(parsedObject)
}
let errorCode = response?.statusCode ?? NSURLErrorCannotParseResponse
return .failure(APIError(code: errorCode, errorUserInfo: nil))
}
}
Fixed by autosuggestion however next error comes
Error: Trailing closure passed to parameter of type 'DataPreprocessor' that does not accept a closure
public static func ObjMappingSerializer(_ keyPath: String?) -> DataResponseSerializer {
return DataResponseSerializer { request, response, data, error in
//LogResponse(response, data: data, error: error)
Logger._reqresLogger.logResponse(response, data: data, error: error)
guard error == nil else {
return .failure(parseErrorResponse(data: data, response: response, errorType: error!))
}
guard let _ = data else {
return .failure(errorForNilData())
}
let JSONToMap = deserializeJSON(request: request, response: response, data: data, error: error, keyPath: keyPath)
if let json = JSONToMap as? [String:Any], let parsedObject = Mapper<T>().map(JSON:json) {
return .success(parsedObject)
}
let errorCode = response?.statusCode ?? NSURLErrorCannotParseResponse
return .failure(APIError(code: errorCode, errorUserInfo: nil))
}
}
Now in Alamofire many methods have been removed in Alamofire 5. How can I fix these errors?

You can no longer initialize a DataResponseSerializer with a closure. I suggest you reevaluate your parsing needs and rebuild around responseDecodable. If you need, you can create your own serializer by adopting ResponseSerializer. Your logic would be the same, just copied into the parse method.

Related

“The data couldn’t be read because it is missing” error when decoding JSON in Swift

I am getting the following error :
The data couldn’t be read because it is missing.
When I run the following code:
var p = [Prevalentie]()
let url = URL(string: "https://data.rivm.nl/covid-19/COVID-19_prevalentie.json")!
let task = URLSession.shared.dataTask(with: url) {
(data: Data?, response: URLResponse?, error: Error?) -> Void in
if let jsonData = data
{
let decoder = JSONDecoder()
do {
p = try decoder.decode([Prevalentie].self, from: jsonData)
print(p)
} catch {
print(error.localizedDescription)
}
}
DispatchQueue.main.async {
}
struct Prevalentie:Codable {
var Date:String
var prev_avg:Int
}
The json data:
{"Date":"2020-02-17","prev_low":693,"prev_avg":1067,"prev_up":1425,"population":"hosp","version":1}
I can get the value of date but not prev_avg.How can I solve this problem?
Thanks,
Maybe one of your response objects has a nil value for prev_avg parameter.
to avoid this error, make prev_avg parameter as an optional ex: let prev_avg:Int?, or get back to your backend if you want to deal with nil parameters.

Why use completionHandlerForConvertData in taskForGETMethod?

Below is code making a request, the completionHandlerForGET was passed to completionHandlerForConvertData handler of function convertDataWithCompletionHandler. But the completionHandlerForConvertData seems doing nothing like printing an error.
Why use it?
func taskForGETMethod(_ method: String, parameters: [String:AnyObject], completionHandlerForGET: #escaping (_ result: AnyObject?, _ error: NSError?) -> Void) -> URLSessionDataTask {
/* 1. Set the parameters */
var parametersWithApiKey = parameters
parametersWithApiKey[ParameterKeys.ApiKey] = Constants.ApiKey as AnyObject?
/* 2/3. Build the URL, Configure the request */
let request = NSMutableURLRequest(url: tmdbURLFromParameters(parametersWithApiKey, withPathExtension: method))
/* 4. Make the request */
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
func sendError(_ error: String) {
print(error)
let userInfo = [NSLocalizedDescriptionKey : error]
completionHandlerForGET(nil, NSError(domain: "taskForGETMethod", code: 1, userInfo: userInfo))
}
/* GUARD: Was there an error? */
guard (error == nil) else {
sendError("There was an error with your request: \(error!)")
return
}
/* GUARD: Did we get a successful 2XX response? */
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
sendError("Your request returned a status code other than 2xx!")
return
}
/* GUARD: Was there any data returned? */
guard let data = data else {
sendError("No data was returned by the request!")
return
}
/* 5/6. Parse the data and use the data (happens in completion handler) */
self.convertDataWithCompletionHandler(data, completionHandlerForConvertData: completionHandlerForGET)
}
/* 7. Start the request */
task.resume()
return task
}
The completionHandlerForConvertData isn't doing anything such as printing an error.
private func convertDataWithCompletionHandler(_ data: Data, completionHandlerForConvertData: (_ result: AnyObject?, _ error: NSError?) -> Void) {
var parsedResult: AnyObject! = nil
do {
//class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any
//Returns a Foundation object from given JSON data.
parsedResult = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as AnyObject
} catch {
let userInfo = [NSLocalizedDescriptionKey : "Could not parse the data as JSON: '\(data)'"]
completionHandlerForConvertData(nil, NSError(domain: "convertDataWithCompletionHandler", code: 1, userInfo: userInfo))
}
completionHandlerForConvertData(parsedResult, nil)
}

How do I get at the underlying Error from an Alamofire error?

For this request:
Alamofire.request("https://google.com").responseCollection { (response: DataResponse<[User]>) in
guard response.result.isSuccess else {
print(response.error)
return
}
}
I see this printed in the console:
Optional(my_app_name.BackendError.jsonSerialization(Alamofire.AFError.responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
0." UserInfo={NSDebugDescription=Invalid value around character 0.}))))
What I've tried:
Alamofire.request("https://google.com").responseCollection { (response: DataResponse<[User]>) in
guard response.result.isSuccess else {
print(response.error)
if let error1 = response.error as? AFError {
print(error1) // Execution DOES NOT reach here.
}
if let error2 = response.error as? BackendError {
print(error2) // Execution DOES reach here.
}
return
}
}
print(error2) above prints:
jsonSerialization(Alamofire.AFError.responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
0." UserInfo={NSDebugDescription=Invalid value around character 0.})))
What I'm trying to do is get at the underlying error so I can parse the domain, code, and userInfo properties.
I created the BackendError enum that Alamofire provides as an example at https://github.com/Alamofire/Alamofire#handling-errors :
enum BackendError: Error {
case network(error: Error) // Capture any underlying Error from the URLSession API
case dataSerialization(error: Error)
case jsonSerialization(error: Error)
case xmlSerialization(error: Error)
case objectSerialization(reason: String)
}
and I also implemented the example generic response object serialization exactly like the example at https://github.com/Alamofire/Alamofire#generic-response-object-serialization :
extension DataRequest {
#discardableResult
func responseCollection<T: ResponseCollectionSerializable>(
queue: DispatchQueue? = nil,
completionHandler: #escaping (DataResponse<[T]>) -> Void) -> Self {
let responseSerializer = DataResponseSerializer<[T]> { request, response, data, error in
guard error == nil else {
return .failure(BackendError.network(error: error!))
}
let jsonSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonSerializer.serializeResponse(request, response, data, nil)
guard case let .success(jsonObject) = result else {
return .failure(BackendError.jsonSerialization(error: result.error!))
}
guard let response = response else {
let reason = "Response collection could not be serialized due to nil response."
return .failure(BackendError.objectSerialization(reason: reason))
}
return .success(T.collection(from: response, withRepresentation: jsonObject))
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
I think there are switches, cases, and casts to and from BackendError, AFError, Error, and/or NSError, but I can't seem to get it.
How can I get at the underlying error so I can parse the domain, code, and userInfo properties?
I'm using Swift 3 and Alamofire 4.3.0 .
I know the answer is a little late ;-). But try this:
... } catch let error as NSError {
print("UnderlyingError: \(String(describing: error.userInfo[NSUnderlyingErrorKey]))")}
For Alamofire 4.3, look at response.result:
if case let .failure(error) = response.result {
let error = error as NSError
print("\(error.domain)")
print("\(error.code)")
print("\(error.userInfo)")
}
Try this
let underlyingError = error.errorUserInfo["NSUnderlyingError"] as! NSError
let code = underlyingError.code
let domain = underlyingError.domain
let userInfo = underlyingError.userInfo

Alamofire 4.0 error from server

Hi I just migrated to alamofire 4 and I just want to send the error coming from the server, I found a couple ways but I just want to make sure that this is the correct way, here is my custom responseobject class
public protocol ResponseObject {
init?(response: HTTPURLResponse, representation: Any)
}
enum BackendError: Error {
case network(error: Error)
case dataSerialization(error: Error)
case jsonSerialization(error: Error)
case xmlSerialization(error: Error)
case objectSerialization(reason: String)
}
extension DataRequest {
public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
func responseObject<T: ResponseObject>(
queue: DispatchQueue? = nil,
completionHandler: #escaping (DataResponse<T>) -> Void)
-> Self
{
let responseSerializer = DataResponseSerializer<T> { request, response, data, error in
guard error == nil else {
let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonResponseSerializer.serializeResponse(request, response, data, nil)
debugPrint(result)
return .failure(BackendError.network(error: error!))
}
let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonResponseSerializer.serializeResponse(request, response, data, nil)
guard case let .success(jsonObject) = result else {
return .failure(BackendError.jsonSerialization(error: result.error!))
}
guard let response = response, let responseObject = T(response: response, representation: jsonObject) else {
return .failure(BackendError.objectSerialization(reason: "JSON could not be serialized: \(jsonObject)"))
}
return .success(responseObject)
}
return response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
I add a debugprint so see the error from the server and I see it but do I have to serialize de data again inside the error?? and how can I pass the message to my custom error?

Alamofire Use of undeclared type 'Serializer'

I have updated to XCode 7 beta 6 and Alamofire needed to be updated to beta 3. In doing so, I'm having to update areas of the code that use Alamofire. One area in particular that I'm having difficulty updating is the code which is used to retrieve an image from a specified URL and load it into a UIImageView.
Previously, the extension for Alamofire that handled that was:
extension Alamofire.Request {
class func imageResponseSerializer() -> Serializer {
return { request, response, data in
if data == nil {
return (nil, nil)
}
let image = UIImage(data: data!, scale: UIScreen.mainScreen().scale)
return (image, nil)
}
}
func responseImage(completionHandler: (NSURLRequest, NSHTTPURLResponse?, UIImage?, NSError?) -> Void) -> Self {
return response(serializer: Request.imageResponseSerializer(), completionHandler: { (request, response, image, error) in
completionHandler(request!, response, image as? UIImage, error)
})
}
}
But not that is throwing the error
Use of undeclared type 'Serializer'
I do realize that Alamofire doesn't use Serializer anymore, but does anyone know where I can find some documentation or examples what to do now when retrieving images?
As you can find in the readme the serialization was rewritten.
You shoudl be able to use the method below:
public protocol ResponseObjectSerializable {
init?(response: NSHTTPURLResponse, representation: AnyObject)
}
extension Request {
public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
if let
response = response,
responseObject = T(response: response, representation: value)
{
return .Success(responseObject)
} else {
let failureReason = "JSON could not be serialized into response object: \(value)"
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(error)
}
case .Failure(let error):
return .Failure(error)
}
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
UIImage serializer for Alamofire, updated for Alamofire 2.0 and Swift 2
Alamofire 2.0 and Swift 2.0

Resources