Как использовать swift generi c Декодируемый протокол в функциях generi c - PullRequest
1 голос
/ 05 марта 2020

Я хотел бы написать обобщенную c функцию, которая анализирует результат и возвращает результат в успешном блоке закрытия или отправляет сообщение об ошибке в блоке ошибки.

Я получаю такую ​​ошибку 'Generi c параметр' T 'не может быть выведен' .

Вот мой пример кода.

let jsonString = """
{
"id": 1,
"msg": "Sample msg"
}
"""

struct Post: Codable {
    var id: String?
    var msg: String?
}

enum PostError: Error {
    case empty
}


func fetch<T:Decodable>(_ completion: @escaping (Result<T?, PostError>) -> Void)  {

        do {
            let data = Data(jsonString.utf8)
            let post = try JSONDecoder().decode(T.self, from: data)
            completion(.success(post))
        }
        catch {
            completion(.failure(.empty))
        }
    }


fetch { res in
        switch res {
        case .success( let p):
            print(p.description)

        case .failure(let error):
            print(error)
        }
    }

Вот ошибка, которую я получаю.

I'm getting error like this.

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Вы можете принять тип generi c в качестве параметра, например:

func fetchObject<T:Decodable>(ofType type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void)  {
   do {
      let data = Data(jsonString.utf8)
      let post = try JSONDecoder().decode(type, from: data)
      completion(.success(post))
   }
   catch {
      completion(.failure(.empty))
   }
}

Использование:

fetchObject(ofType: Post.self) { res in
   switch res {
       case .success(let post):
          print(post.description)
       case .failure(let error):
          print(error)
   }
}
0 голосов
/ 05 марта 2020

Я понимаю, что вы пытаетесь сделать, но главная проблема в том, что вы никогда не указываете тип. Компилятор знает, что вы хотите вызвать fetch, но он не знает, что вы хотите получить или что анализировать.

Если вы посмотрите на ваш fetch вызов, то нигде не найдется, где компилятор мог бы сообщить, что вы пытаетесь сделать или что вы ожидаете.

У вас либо есть до:

1. Передайте тип в качестве параметра

func fetch<T: Decodable>(_ type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void)  {

    do {
        let data = Data(jsonString.utf8)
        let post = try JSONDecoder().decode(T.self, from: data)
        completion(.success(post))
    }
    catch {
        completion(.failure(.empty))
    }
}


fetch(Post.self) { res in
        switch res {
        case .success(let p):
            print(p)

        case .failure(let error):
            print(error)
        }
    }

или ...

2. Укажите тип при создании экземпляра объекта, членом которого является функция:

struct Fetcher<T: Decodable> {

    func fetch(_ completion: @escaping (Result<T, PostError>) -> Void)  {

        do {
            let data = Data(jsonString.utf8)
            let post = try JSONDecoder().decode(T.self, from: data)
            completion(.success(post))
        }
        catch {
            completion(.failure(.empty))
        }
    }
}

let fetcher = Fetcher<Post>()
fetcher.fetch { res in
    switch res {
    case .success(let p):
        print(p)

    case .failure(let error):
        print(error)
    }
}
...