@devxoul Привет! Я пытаюсь использовать протокол ImmutableMappable
, но в README нет объяснения того, как использовать вместе с вложенными объектами.
Я хочу попробовать что-нибудь простое:
struct Father: ImmutableMappable {
let name: String
let children: [Child]
init(map: Map) throws {
name = try map.value("name")
children = try map.value("children", using: ArrayTransform<Child>())
}
}
struct Child: ImmutableMappable {
let age: Int
init(map: Map) throws {
age = try map.value("age")
}
}
Значит нет Transform
работы с массивами? Итак, я написал приведенный ниже преобразователь, вдохновленный ListTransformer из ObjectMapper-Realm.
struct ArrayTransform<T: ImmutableMappable> {}
extension ArrayTransform: TransformType {
typealias Object = [T]
typealias JSON = [Any]
func transformFromJSON(_ value: Any?) -> Object? {
if let objects = Mapper<T>().mapArray(JSONObject: value) {
let list = Object()
list.append(objectsIn: objects)
return list
}
return nil
}
public func transformToJSON(_ value: Object?) -> JSON? {
return value?.flatMap { $0.toJSON() }
}
}
Результат при ошибке компиляции: Ambigious use of 'mapArray(JSONObject:)'
Моя теория состоит в том, что это потому, что компилятор находит метод в этих двух областях:
public extension Mapper where N: ImmutableMappable
public final class Mapper<N: BaseMappable> {
Но поскольку ImmutableMappable
наследуется от BaseMappable
, обе функции являются допустимыми кандидатами.
И еще, нужно ли мне для этого писать Трансформатор?
Вам не обязательно использовать материал ArrayTransform. Просто сделайте это следующим образом:
init(map: Map) throws {
// ...
children = try map.value("children")
}
PS: Причина сбоя сборки в том, что вы не пометили `mapArray ()` с помощью `try`.let objects = попробуйте Mapper() .mapArray (JSONObject: значение) // сделай что-нибудь
@devxoul Привет, спасибо за ответ! Хе-хе, да, это было проще, чем я думал! 😅
Что касается вашего ответа P.S.
- я все еще не могу заставить его работать! Сейчас я пытаюсь реализовать расширение Alamofire + ObjectMapper аналогично AlamofireObjectMapper , но для ImmutableMappable
Я все еще получаю ошибку компиляции Ambigious use of map....
, ищите два комментария "// Compilation Error"
в приведенном ниже коде.
Что я делаю неправильно?
import Foundation
import Alamofire
import ObjectMapper
extension DataRequest {
enum ErrorCode: Int {
case noData = 1
case dataSerializationFailed = 2
}
internal static func newError(_ code: ErrorCode, failureReason: String) -> NSError {
let errorDomain = "com.alamofireobjectmapper.error"
let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
let returnError = NSError(domain: errorDomain, code: code.rawValue, userInfo: userInfo)
return returnError
}
public static func ObjectMapperSerializer<T: ImmutableMappable>(_ keyPath: String?, mapToObject object: T? = nil, context: MapContext? = nil) -> DataResponseSerializer<T> {
return DataResponseSerializer { request, response, data, error in
guard error == nil else {
return .failure(error!)
}
guard let _ = data else {
let failureReason = "Data could not be serialized. Input data was nil."
let error = newError(.noData, failureReason: failureReason)
return .failure(error)
}
let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonResponseSerializer.serializeResponse(request, response, data, error)
let JSONToMap: Any?
if let keyPath = keyPath , keyPath.isEmpty == false {
JSONToMap = (result.value as AnyObject?)?.value(forKeyPath: keyPath)
} else {
JSONToMap = result.value
}
if let object = object {
_ = Mapper<T>().map(JSONObject: JSONToMap, toObject: object)
return .success(object)
} else {
do {
// Compilation Error: "Amigious user of 'map(JSONObject:)'"
let parsedObject = try Mapper<T>(context: context).map(JSONObject: JSONToMap)
return .success(parsedObject)
} catch let error {
fatalError("Mapping error: \(error)")
}
}
let failureReason = "ObjectMapper failed to serialize response."
let error = newError(.dataSerializationFailed, failureReason: failureReason)
return .failure(error)
}
}
<strong i="16">@discardableResult</strong>
public func responseObject<T: ImmutableMappable>(queue: DispatchQueue? = nil, keyPath: String? = nil, mapToObject object: T? = nil, context: MapContext? = nil, completionHandler: <strong i="17">@escaping</strong> (DataResponse<T>) -> Void) -> Self {
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperSerializer(keyPath, mapToObject: object, context: context), completionHandler: completionHandler)
}
public static func ObjectMapperArraySerializer<T: ImmutableMappable>(_ keyPath: String?, context: MapContext? = nil) -> DataResponseSerializer<[T]> {
return DataResponseSerializer { request, response, data, error in
guard error == nil else {
return .failure(error!)
}
guard let _ = data else {
let failureReason = "Data could not be serialized. Input data was nil."
let error = newError(.dataSerializationFailed, failureReason: failureReason)
return .failure(error)
}
let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
let result = jsonResponseSerializer.serializeResponse(request, response, data, error)
let JSONToMap: Any?
if let keyPath = keyPath, keyPath.isEmpty == false {
JSONToMap = (result.value as AnyObject?)?.value(forKeyPath: keyPath)
} else {
JSONToMap = result.value
}
do {
// Compilation Error: "Amigious user of 'map(JSONObject:)'"
let parsedObject = try Mapper<T>(context: context).mapArray(JSONObject: JSONToMap)
return .success(parsedObject)
} catch let error {
fatalError("Failed to map, error: \(error)")
}
let failureReason = "ObjectMapper failed to serialize response."
let error = newError(.dataSerializationFailed, failureReason: failureReason)
return .failure(error)
}
}
<strong i="18">@discardableResult</strong>
public func responseArray<T: ImmutableMappable>(queue: DispatchQueue? = nil, keyPath: String? = nil, context: MapContext? = nil, completionHandler: <strong i="19">@escaping</strong> (DataResponse<[T]>) -> Void) -> Self {
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperArraySerializer(keyPath, context: context), completionHandler: completionHandler)
}
}
@Sajjon Кстати, AlamofireObjectMapper теперь поддерживает ImmutableMappable
в v4.1
Закройте это, поскольку новая версия AlamofireObjectMapper должна решить проблему. Не стесняйтесь комментировать, и я могу повторно открыть заявку, если это необходимо.
Самый полезный комментарий
@Sajjon Кстати, AlamofireObjectMapper теперь поддерживает
ImmutableMappable
в v4.1