Функция Generi c, которая принимает T.Type или [T] .Type в качестве параметра и возвращает T - PullRequest
0 голосов
/ 05 августа 2020

Я пытаюсь написать общую c функцию, которая принимает Generi c T.Type в качестве аргумента функции, но не принимает T.Type как массив

public protocol Mappable {
    
}

class User: Mappable {
    var name: String?
}

class MyClass {
    func request<T: Mappable>(responseType: T.Type) -> T {
        let objT = .....
        return objT
    }
}
let myCls = MyClass()
myCls.request(responseType: User.self) // Works as expected
myCls.request(responseType: [User].self) // Error: Instance method 'request(responseType:)' requires that '[User]' conform to 'Mappable'

Эксперимент : Если я заменю Mappable на Decodable в приведенном выше коде, он будет работать нормально. но я хочу использовать свой Protocol, а не Decodable

Я хочу добиться того же, что и

struct Car: Decodable {
    var name: String?
}

let data = "{\"name\": \"Lamborghini\"}".data(using: .utf8)
let dataArray = "[{\"name\": \"Lamborghini\"}, {\"name\": \"Ferrari\"}]".data(using: .utf8)

let car = try! JSONDecoder().decode(Car.self, from: data!) // Will return single object of Car
let cars = try! JSONDecoder().decode([Car].self, from: dataArray!) // Will return Array of Car

Я не могу понять, почему он работает с Decodable и не с моим Mappable Protocol

1 Ответ

0 голосов
/ 05 августа 2020

это потому, что массив декодируется, если его тип элемента декодируется.

extension Array: Decodable where Element: Decodable {
  /// Creates a new array by decoding from the given decoder.
  ///
  /// This initializer throws an error if reading from the decoder fails, or
  /// if the data read is corrupted or otherwise invalid.
  ///
  /// - Parameter decoder: The decoder to read data from.
  public init(from decoder: Decoder) throws {
    self.init()

    var container = try decoder.unkeyedContainer()
    while !container.isAtEnd {
      let element = try container.decode(Element.self)
      self.append(element)
    }
  }
}

вы можете ссылаться на реализацию из https://github.com/apple/swift/blob/master/stdlib/public/core/Codable.swift

Я думаю, ваша функция вызов myCls.request(responseType: [User].self) не выполнен, потому что T - [User], это не Mappable.

...