Closed balazsgerlei closed 7 years ago
If I'm correct, it would be something like this (correct me if I'm wrong):
import Alamofire
import OCMapper
public extension Request {
public func responseObjects<T: NSObject> (type: T.Type, completionHandler: Result<[T]?, NSError> -> Void) -> Self {
return response(responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments)) { response in
switch response.result {
case .Success:
let objects = ObjectMapper.sharedInstance().objectFromSource(response.result.value, toInstanceOfClass: type) as? [T]
completionHandler(Result.Success(objects))
case .Failure(let error):
completionHandler(Result.Failure(error))
}
}
}
public func responseObject<T: NSObject> (type: T.Type, completionHandler: Result<T?, NSError> -> Void) -> Self {
return response(responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments)) { response in
switch response.result {
case .Success:
let object = ObjectMapper.sharedInstance().objectFromSource(response.result.value, toInstanceOfClass: type) as? T
completionHandler(Result.Success(object))
case .Failure(let error):
completionHandler(Result.Failure(error))
}
}
}
}
Hey, I don't have Alamofire around or a test project, but maybe
public func responseObjects<T: NSObject> (type: T.Type, completionHandler: Result<[T]?, NSError> -> Void) -> Self {
to
public func responseObjects<T: NSObject> (type: T.Type, completionHandler: Result<[T], ErrorType> -> Void) -> Self {
Why switching the optional to a normal type make it better?
However I realized that my suggested implementation is not the best solution, I will suggest another way soon, but I have to try it out properly first. My fault was that these two "responseObject" methods should use the Alamofire type "Response" instead of "Result".
Ok, after some experiment I now get why you suggested changing "T?" to "T" and "[T]?" to "[T]": to avoid double optionals. Handling serialization failures is better by using Errors than returning success with Optional value.
right for errors you want to use Failure
public enum Result<Value, Error: ErrorType> {
case Success(Value)
case Failure(Error)
Haven't tested this just wrote it based on what you have
extension Request {
public func responseObjects<T: NSObject> (type type: T.Type, completion: Result<[T], NSError> -> Void) -> Self {
return responseJSON {
switch $0.result {
case .Success(let json):
guard let object = ObjectMapper.sharedInstance().objectFromSource(json, toInstanceOfClass: type) as? [T] else {
let errorResult = Result.Failure(NSError(domain: "replaceMeWithErrorTypeEnum", code: 0, userInfo: nil))
completion(errorResult)
return
}
completion(Result.Success(object))
case .Failure(let error):
completion(Result.Failure(error))
}
}
}
}
Usage
request.responseObjects(type: User.self) {
switch $0 {
case .Success(let users):
print(users.count)
case .Failure(let error):
print(error)
}
}
I came up with something similar, though I prefer having if-else for the success and failure rather than guard, but that is just personal preference. Also, I declared a domain and error code for errors.
import Alamofire
import OCMapper
public extension Request {
public static let OcMapperErrorDomain = "com.alamofire.ocmapper.error"
public enum ErrorCode: Int {
case ObjectSerializationFailed = -7000
}
public func responseObjects<T: NSObject> (type: T.Type, completionHandler: Response<[T], NSError> -> Void) -> Self {
return response(responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments)) {
response
in
switch response.result {
case .Success:
if let objects = ObjectMapper.sharedInstance().objectFromSource(response.result.value, toInstanceOfClass: type) as? [T] {
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Success(objects)))
} else {
let failureReason = "Objects could not be serialized from JSON."
let userInfo: Dictionary<NSObject, AnyObject> = [NSLocalizedFailureReasonErrorKey: failureReason]
let error = NSError(domain: Request.OcMapperErrorDomain, code: ErrorCode.ObjectSerializationFailed.rawValue, userInfo: userInfo)
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Failure(error)))
}
case .Failure(let error):
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Failure(error)))
}
}
}
public func responseObject<T: NSObject> (type: T.Type, completionHandler: Response<T, NSError> -> Void) -> Self {
return response(responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments)) {
response
in
switch response.result {
case .Success:
if let object = ObjectMapper.sharedInstance().objectFromSource(response.result.value, toInstanceOfClass: type) as? T {
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Success(object)))
} else {
let failureReason = "Object could not be serialized from JSON."
let userInfo: Dictionary<NSObject, AnyObject> = [NSLocalizedFailureReasonErrorKey: failureReason]
let error = NSError(domain: Request.OcMapperErrorDomain, code: ErrorCode.ObjectSerializationFailed.rawValue, userInfo: userInfo)
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Failure(error)))
}
case .Failure(let error):
completionHandler(Response(request: response.request, response: response.response, data: response.data, result: Result.Failure(error)))
}
}
}
}
Why are you closing this? As I detailed in #59, I only asked the example to be added to the README.
Hi!
I see there is an Alamofire Request extension example in the README, but if I'm correct it is not for the newest, 3.x version of Alamofire. Can you update it to show how can OCMapper be used with Alamofire 3.x. It would be really appreciated!