Since I updated Alamofire I get the errors: Type Request has no member JSONResponseSerializer and cannot call value of non-function type HTTPURLResponse
I have already switched Response to DataResponse but I still get the error.
Code:
extension Alamofire.Request {
func responseUserEventsArray(_ completionHandler: #escaping (DataResponse<UserEventsWrapper>) -> Void) -> Self {
let responseSerializer = DataResponseSerializer<UserEventsWrapper> { request, response, data, error in
guard error == nil else
{
return .failure(error!)
}
guard let responseData = data else {
return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
}
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .allowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, responseData, error)
switch result {
case .Success(let value):
let json = JSON(value)
let wrapper = UserEventsWrapper()
wrapper.next = json["eventhistory"]["next_page_url"].stringValue
wrapper.previous = json["eventhistory"]["prev_page_url"].stringValue
wrapper.count = json["eventhistory"]["total"].intValue
var allUserEvents:Array = Array<UserEvents>()
print(json)
let results = json["eventhistory"]["data"]
print(results)
for jsonAds in results
{
print(jsonAds.1)
let adsData = UserEvents(json: jsonAds.1, id: Int(jsonAds.0))
allUserEvents.append(adsData)
}
wrapper.usereventsitems = allUserEvents
return .success(wrapper)
case .Failure(let error):
return .Failure(error)
}
}
return response(responseSerializer: responseSerializer,completionHandler: completionHandler)
}
}
EDITED
Change
Request.JSONResponseSerializer to DataRequest.jsonResponseSerializer
extension Alamofire.Request to extension Alamofire.DataRequest – Mat0
.success and .failure - FranMowinckel
Related
Hello I am trying to extract a json. However I am getting an error saying Cannot convert value of type 'Data' to expected argument type 'NSData'. Is there something that I am doing wrong?
success: { (response) -> Void in
var dataStream: Data = Data.init(referencing: response!)
do {
let data = try JSONSerialization.jsonObject(with: dataStream, options: JSONSerialization.ReadingOptions.mutableContainers)as AnyObject
}catch{
}
if let id = response!["money"]as? String {
print(id)
}
}){ (error) -> Void in
print("error")
}
}
Update2
let request = Alamofire.request(apiUrl, method: .get)
request.responseJSON { response in
switch response.result
{
case .success:
success(response.result.value as AnyObject)
case .failure(let error):
failure(error as NSError)
}
}
}
Your problem is here
var dataStream: Data = Data.init(referencing: response!)
in Docs
init(referencing reference: NSData)
response should be of type NSData not Data , you may try
let responseDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
note cast to expected return whether it's dictionary or array
this
if let id = response!["money"]as? String {
print(id)
}
should be replaced with
if let id = responseDict!["money"]as? String {
print(id)
}
You can try Alamofire with SwiftyJson
Alamofire.request("https://yourlinkdownloadjson/abc").responseJSON { response in
debugPrint(response)
if let json = response.data {
let data = JSON(data: json)
print("data\(data["money"])")
}
}
I read answer from other questions also but not able to solve:
I tried with following way but getting same error at the line of
return response(responseSerializer: responseSerializer,completionHandler: completionHandler)
please help us in how you add #escaping in following method.
public func JSONResponseObject<T: ResponseObjectSerializable>(_ completionHandler: #escaping (DataResponse<T>) -> Void) -> Self {
let responseSerializer = DataResponseSerializer<T> { request, response, data, error in
guard error == nil else { return .failure(error!) }
let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonResponseSerializer.serializeResponse(request, response, data, nil)
print("result: \(result.value)")
switch result {
case .success(let value):
let json = JSON(value)
print("JSON: \(json)")
if let
response = response,
let responseObject = T(response: response, representation: value as AnyObject)
{
return .success(responseObject)
} else {
let error = Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: -6006 as! Error)
return .failure(error as! Error)
}
case .failure(let error):
let json = JSON(error)
print("JSON: \(json)")
return .failure(error)
}
}
return response(responseSerializer: responseSerializer,completionHandler: completionHandler)
}
I solved now in following way
I set extension DataRequest { } instead in extension Request { }
My moto is Auto search, I have been trying with URLSession, When i am trying to search slowly the requests are handled as expected(when there is no text the response is empty i mean the placesarray) but when i am trying to clear the text or hit any searchtext speedily then the previous request response are being appended in the placesarray. I tried with cancelling the previous request yet i am not getting the result(i.e previous response not be appended)
func autoSearch(text:String){
let urlRequest = URLRequest(url: self.getQueryFormedBingURL()!)
let session = URLSession.shared
session.getTasksWithCompletionHandler
{
(dataTasks, uploadTasks, downloadTasks) -> Void in
// self.cancelTasksByUrl(tasks: dataTasks as [URLSessionTask])
self.cancelTasksByUrl(tasks: uploadTasks as [URLSessionTask])
self.cancelTasksByUrl(tasks: downloadTasks as [URLSessionTask])
}
let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) -> Void in
print("response \(response)")
if let data = data {
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
if let jsonDic = json as? NSDictionary {
let status = jsonDic.returnsObjectOrNone(forKey: "statusCode") as! Int
if status == 200 {
if let resourceSetsArr = jsonDic.returnsObjectOrNone(forKey: "resourceSets") as? NSArray {
if let placesDict = resourceSetsArr.object(at: 0) as? NSDictionary {
if let resourceArr = placesDict.object(forKey: "resources") as? NSArray, resourceArr.count > 0 {
if let _ = self.placesArray {
self.placesArray!.removeAll()
}
for loopCounter in 0...resourceArr.count - 1 {
let modalClass:BingAutoCompletePlace = BingAutoCompletePlace(responseDict: resourceArr[loopCounter] as! NSDictionary)
self.placesArray?.append(modalClass)
}
completion(self.placesArray!)
}
else { //URL Success, where there no places with the given search string
completion([])
}
}
}
}
}
}
else if let response = response as? HTTPURLResponse , 400...499 ~= response.statusCode {// When url fails
if let _ = error {
print("error=\(error!.localizedDescription)")
}
completion([])
}
else {
if let _ = error {
print("error=\(error!.localizedDescription)")
}
completion([])
}
}
})
task.resume()
}
//Request cancellation
private func cancelTasksByUrl(tasks: [URLSessionTask]) {
for task in tasks
{
task.cancel()
}
}
Unfortunately, the framework does not guarantee any order in which tasks finish -- because this depends on the running time. It could also be that you're in a completion handler of a currently cancelled task.
To circumvent this, you could do the following:
Create a private instance variable to store the most-recent task
Cancel everything else as before
In the completion handler
check if the task is still the most recent task (like if (task !== self.currentTask) {return})
create a local Array to store the data
Update the view controllers array in the main thread (DispatchQueue.main.async(...))
I cleaned up you code a litte (using guard statments to minimize the nesting). Maybe you should also
Empty the array in all the error / empty cases (instead of simple return from the guard statement)
hand-in the task to the completion call and check there again if the task is still the currentTask. This would also be a good way to reset currentTask to nil.
Just adopt it to your needs :-)
var currentTask:URLSessionDataTask?
func autoSearch(text:String){
let completion:(_ x:[AnyObject])->() = {_ in }
let urlRequest = URLRequest(url: self.getQueryFormedBingURL()!)
let session = URLSession.shared
session.getTasksWithCompletionHandler
{
(dataTasks, uploadTasks, downloadTasks) -> Void in
// self.cancelTasksByUrl(tasks: dataTasks as [URLSessionTask])
self.cancelTasksByUrl(tasks: uploadTasks as [URLSessionTask])
self.cancelTasksByUrl(tasks: downloadTasks as [URLSessionTask])
}
var task:URLSessionDataTask!
task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) -> Void in
print("response \(response)")
if (task !== self.currentTask) {
print("Ignore this task")
return
}
if let error = error {
print("response error \(error)")
}
guard let data = data else { return }
let json = try? JSONSerialization.jsonObject(with: data, options: [])
var newPlacesArray = [AnyObject]() // Empty array of whichever type you want
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
guard let jsonDic = json as? NSDictionary else { return }
let status = jsonDic.returnsObjectOrNone(forKey: "statusCode") as! Int
if status == 200 {
guard let resourceSetsArr = jsonDic.returnsObjectOrNone(forKey: "resourceSets") as? NSArray else { return }
guard let placesDict = resourceSetsArr.object(at: 0) as? NSDictionary else { return }
guard let resourceArr = placesDict.object(forKey: "resources") as? NSArray, resourceArr.count > 0 else {
//URL Success, where there no places with the given search string
DispatchQueue.main.async {completion(newPlacesArray)}
return
}
for loopCounter in 0...resourceArr.count - 1 {
let modalClass:BingAutoCompletePlace = BingAutoCompletePlace(responseDict: resourceArr[loopCounter] as! NSDictionary)
newPlacesArray.append(modalClass)
}
DispatchQueue.main.async {completion(newPlacesArray)}
}
}
else if let response = response as? HTTPURLResponse , 400...499 ~= response.statusCode {// When url fails
if let _ = error {
print("error=\(error!.localizedDescription)")
}
DispatchQueue.main.async {completion(newPlacesArray)}
}
else {
if let _ = error {
print("error=\(error!.localizedDescription)")
}
DispatchQueue.main.async {completion(newPlacesArray)}
}
})
self.currentTask = task
task.resume()
}
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?
I'm having trouble with the ResponseSerializer I get an unresolved identifier and for Response I get an undeclared type. I've read from alamofire migration doc that Response has been changed to multiple types. So I should change Response->DataReponse but this means I can only pass one argument like:
// What I have
Response(<ListWrapper, NSError>)
// What I should change it to?
DataResponse(<ListWrapper>)
How can I still recieve the Error this way and more importantly how do I migrate the extension to alamofire 4?
My class:
class List{
var idNumber: String?
var title: String?
var posterPath: String?
var release: String?
required init(json: JSON, id: Int?)
{
self.idNumber = json[ListFields.Id.rawValue].stringValue
self.title = json[ListFields.Title.rawValue].stringValue
self.posterPath = json[ListFields.PosterPath.rawValue].stringValue
self.release = json[ListFields.Release.rawValue].stringValue
}
class func setURL_APPEND(_ url: String)
{
URL_APPEND = url
}
// MARK: Endpoints
class func endpointForList() -> String
{
return URL_APPEND
}
fileprivate class func getListAtPath(_ path: String, completionHandler: #escaping (ListWrapper?, NSError?) -> Void) {
Alamofire.request(path)
.responseListArray { response in
if let error = response.result.error
{
completionHandler(nil, error)
return
}
completionHandler(response.result.value, nil)
}
}
class func getList(_ completionHandler: #escaping (ListWrapper?, NSError?) -> Void)
{
getListAtPath(List.endpointForList(), completionHandler: completionHandler)
}
}
// Problem is here:
// for ResponseSerializer I get an unresolved identifier
// and for Response I get an undeclared type
extension Alamofire.Request {
func responseListArray(_ completionHandler: #escaping (Response<ListWrapper, NSError>) -> Void) -> Self {
let responseSerializer = ResponseSerializer<ListWrapper, NSError> { request, response, data, error in
guard error == nil else
{
return .failure(error!)
}
guard let responseData = data else {
let failureReason = "Array could not be serialized because input data was nil."
let error = Alamofire.Error.errorWithCode(.dataSerializationFailed, failureReason: failureReason)
return .failure(error)
}
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .allowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, responseData, error)
switch result {
case .success(let value):
let json = SwiftyJSON3.JSON(value)
let wrapper = ListWrapper()
var allList:Array = Array<List>()
wrapper.totalCount = json["favorite_count"].intValue
// print(json)
let results = json["items"]
// print(results)
for jsonList in results
{
//print(jsonList.1)
let list = List(json: jsonList.1, id: Int(jsonList.0) )
if (list.posterPath == "")
{
continue
}
else
{
//print(movies.posterPath)
allList.append(list)
}
}
wrapper.results = allList
return .success(wrapper)
case .failure(let error):
return .failure(error)
}
}
return response(responseSerializer: responseSerializer,completionHandler: completionHandler)
}
}
Bro try below code see:
func responseListArray(_ completionHandler: #escaping (Response<ListWrapper>) -> Void) -> Self {
let responseSerializer = ResponseSerializer<ListWrapper> { request, response, data, error in
guard error == nil else
{
return .failure(error!)
}
guard let responseData = data else {
return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
}
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .allowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, responseData, error)
switch result {
case .success(let value):
let json = SwiftyJSON3.JSON(value)
let wrapper = ListWrapper()
var allList:Array = Array<List>()
wrapper.totalCount = json["favorite_count"].intValue
// print(json)
let results = json["items"]
// print(results)
for jsonList in results
{
//print(jsonList.1)
let list = List(json: jsonList.1, id: Int(jsonList.0) )
if (list.posterPath == "")
{
continue
}
else
{
//print(movies.posterPath)
allList.append(list)
}
}
wrapper.results = allList
return .success(wrapper)
case .failure(let error):
return .failure(error)
}
}
return response(responseSerializer: responseSerializer,completionHandler: completionHandler)
}