I am trying to use this piece of code I got raywenderlich.com in Xcode 7. But at the return line is giving me error saying
Cannot convert return expression of type (NilLiteralConvertible,
NilLiteralConvertible) to return type Result<UIImage>
extension Alamofire.Request {
public static func imageResponseSerializer() -> GenericResponseSerializer<UIImage> {
return GenericResponseSerializer { request, response, data in
if data == nil {
return (nil, nil)
}
let image = UIImage(data: data!, scale: UIScreen.mainScreen().scale)
return (image, nil)
}
}
public func responseImage(completionHandler: (NSURLRequest, NSHTTPURLResponse?, UIImage?, NSError?) -> Void) -> Self {
return response(responseSerializer: Request.imageResponseSerializer(), completionHandler: completionHandler)
}
}
See original code at http://www.raywenderlich.com/85080/beginning-alamofire-tutorial
It looks like when you converted your project to Swift 2 you also upgraded to AlamoFire 2.x. The tutorial was written for Swift 1.2 where the closure's signature was:
(NSURLRequest?, NSHTTPURLResponse?, NSData?) -> (SerializedObject?, NSError?)
With AlamoFire 2 the signature is now:
(NSURLRequest?, NSHTTPURLResponse?, NSData?) -> Result<SerializedObject>
This means your method needs to return .Success(image!) in the passing condition and .Failure(data, myError) in the failing condition. It also means you can't just pass image without unwrapping since that initializer is nullable and the result's parameter is not.
Your serializer could look something like this:
return GenericResponseSerializer { request, response, data in
guard let validData = data else {
let error = ...
return .Failure(data, error)
}
guard let image = UIImage(data: validData, scale: UIScreen.mainScreen().scale) else {
let error = ...
return .Failure(data, error)
}
return .Success(image)
}
For your error you could either define your own ErrorType enum that will be helpful to you or use AlamoFire.Error:
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: "Image parsing failed.")
Your responseImage function will need a similar change:
public func responseImage(completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<UIImage>) -> Void) -> Self {
return response(responseSerializer: Request.imageResponseSerializer(), completionHandler: completionHandler)
}
This will in turn require you to update code that uses responseImage but those error messages should be helpful.
It work for me, remove old Alamofire from Ray's sample, and add last version form git https://github.com/Alamofire/Alamofire, and change sample XMLResponseSerializer , for UIImage it looks like :
extension Alamofire.Request {
public static func imageResponseSerializer() -> ResponseSerializer<UIImage, NSError> {
return ResponseSerializer { request, response, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data else {
let failureReason = "Image parsing failed."
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
return .Failure(error)
}
guard let image = UIImage(data: validData, scale: UIScreen.mainScreen().scale) else {
let failureReason = "Image format failed."
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
return .Failure( error)
}
return .Success(image)
}
}
public func responseImage(completionHandler: Response<UIImage, NSError> -> Void) -> Self {
return response(responseSerializer: Request.imageResponseSerializer(), completionHandler: completionHandler)
}
}
Related
I am getting below error
Generic parameter 'T' could not be inferred
I have created a method and when I am trying to call that method then getting that error. I am adding both methods below.
func requestNew<T> ( _ request: URLRequest, completion: #escaping( Result< T , NetworkError>) -> Void ) where T : Decodable {
URLCache.shared.removeAllCachedResponses()
print("URL \((request.url as AnyObject).absoluteString ?? "nil")")
//use the currentrequest for cancel or resume alamofire request
currentAlamofireRequest = self.sessionManager.request(request).responseJSON { response in
//validate(statusCode: 200..<300)
if response.error != nil {
var networkError : NetworkError = NetworkError()
networkError.statusCode = response.response?.statusCode
if response.response?.statusCode == nil{
let error = (response.error! as NSError)
networkError.statusCode = error.code
}
//Save check to get the internet connection is on or not
if self.reachabilityManager?.isReachable == false {
networkError.statusCode = Int(CFNetworkErrors.cfurlErrorNotConnectedToInternet.rawValue)
}
completion(.failure(networkError))
}else{
print("response --- > ",String(data: response.data!, encoding: .utf8) ?? "No Data found")
if let responseObject = try? JSONDecoder().decode(T.self, from: response.data!) {
completion(.success(responseObject.self))
}else {
}
}
}
}
Below is screenshot of error
![
]1
func getVersion1(complete :#escaping (Response<Version>) -> Void, failure:#escaping onFailure) {
self.network.requestNew(self.httpRequest) { (result) in
print("hello")
}
When Swift cannot infer the generic parameter, although it accepts the generic declaration of the method, you can specify the type by passing type fixed parameters.
Try this:
func getVersion1(complete :#escaping (Response<Version>) -> Void, failure:#escaping onFailure) {
self.network.requestNew(self.httpRequest) { (result: Result<Version, NetworkError>) in
print("hello")
}
}
You may need to change Result<Version, NetworkError> to Result<SomeDecodableType, NetworkError>, if Version is not the type you expect from the request.
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)
}
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
I'm trying to write generic serializers for Alamofire and I'm trying to understand how I can make the generic response serializers determine if there was an error and return a custom error object instead (The server returns an error dictionary in that situation).
Any input would be appreciated!
Here's the example code that I'm currently using:
#objc public protocol ResponseObjectSerializable {
init?(response: NSHTTPURLResponse, representation: AnyObject)
}
extension Alamofire.Request {
public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
let serializer: Serializer = { (request, response, data) in
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
if response != nil && JSON != nil {
return (T(response: response!, representation: JSON!), nil)
} else {
return (nil, serializationError)
}
}
return response(serializer: serializer, completionHandler: { (request, response, object, error) in
completionHandler(request, response, object, error)
})
}
}