Функция Swift Generics с выходом из закрытия - PullRequest
0 голосов
/ 29 мая 2018

У меня есть метод:

func getUsers(completion: @escaping (_ users: [User]?,_ error: String?)->()) { router.request(.getUsers) { (data, response, error) in
 var users = [User]()
 users = try JSONDecoder().decode(Array<User>.self, from: responseData)
}

Но я хочу сделать эту функцию более общей. Я пытался :

    func getUsers<T: Decodable>(completion: @escaping (_ users: [T]?,_ error: String?)->()) { router.request(.getUsers) { (data, response, error) in 
      var users = [T]()
      users = try JSONDecoder().decode(Array<T>.self, from: responseData)
      completion(users, nil)
}

Но когда я вызываю этот пользовательский массив func из-за выхода из закрытия, это [_].Если я просто использую только массив пользователей T, это [User.Type], и ​​он не соответствует Decodable, поэтому я могу сделать JSONDecoder().decode.Как это должно выглядеть?

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Привет, Hds Вы правильно выполнили большую часть работы, только один упущенный момент - это знание о том, как работают Decodables.

Массив Decodable также Decodable.Итак, я пытаюсь сказать, что вам не нужно явно упоминать, что вы хотите декодировать Array<T>.self, вы можете поместить T.self, если вы перешли к функции, которую вы ожидаете Array<T>.self, такT => Array<T>

Так что в вашем случае, когда вы вызываете эту функцию и передаете [User] в качестве универсального параметра, T будет Array<User>.self при декодировании.Вот как должен выглядеть код.Я не уверен, что код будет компилироваться на 100%, потому что у меня есть некоторые недостающие компоненты, но это помогает понять.

func get<T:Deocdable>(completion: @escaping (_ object: T?,_ error: String?) -> ()) {
    router.request(.getUsers) { (data, response, error) in
        do {
            let object = try JSONDecoder().decode(T.self, from: responseData)
        } catch {
            fatalError("Decoding failed because: ", error.localizedDescription)
        }
}

Также я добавил блок do catch, потому что try JSONDecoder() throws.

Кроме того, чтобы добавить, как вы должны вызывать метод, он выглядит следующим образом:

get { (users: [User]?, error) in

}

Надеюсь, это поможет.

0 голосов
/ 29 мая 2018

Массив <Пользователь> не может быть преобразован в '[_]?'

Это из-за _ пользователей: [T]? тип Необязательно

Ваш метод работает нормально, вам просто нужно определить необязательный массив.

 self.getUsers{ (res:Array<User>?, error) in

 }

Я создал один похожий

 func getUsers<T: Decodable>(completion: @escaping (_ users: [T]?,_ error: String?)->()) {

        URLSession.shared.dataTask(with: URL(string: "test")!) { (data, res, error) in
            guard let resData = data else  {completion(nil,"data is nil"); return}
            do {
                var users = [T]()
                users = try JSONDecoder().decode(Array<T>.self, from:resData)
                completion(users, nil)

            } catch {
                completion(nil, error.localizedDescription)
            }
        }

И назовите это

     self.getUsers{ (res:Array<User>?, error) in

    }

Вот структура

struct User :Codable {
    var name:String?
}
...